Part 1: Whole Game

Chapter 1: Visualization

#Loading needed libraries
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ lubridate 1.9.2     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.0── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(palmerpenguins)
library(ggthemes)
library(ggplot2)
library(lvplot)
library(ggbeeswarm)
#Different ways to view tibble data
penguins
glimpse(penguins)
View(penguins)
?penguins
# plotting
ggplot(data=penguins, mapping = aes(x=flipper_length_mm,y=body_mass_g)) +
  geom_point(mapping = aes(color=species,shape=species)) +
  geom_smooth(method = "lm")+
  labs(title="Body mass and flipper length",
       subtitle = "Dimensions for Adelie, Chinstrap, and Gentoo Penguins",
       x = "Flipper length (mm)", y="Body mass (g)",
       color="Species",shape="Species")+
  scale_color_colorblind()

#Exercise 1

#Question 1
nrow(penguins)
[1] 344
ncol(penguins)
[1] 8
q1="There are 344 rows and 8 columns within the penguins dataset"
#Question 2
?penguins
q2="The bill depth is the length from the top of the culmen bill to the bottom of the culmen bill."
#Question 3
ggplot(data = penguins,mapping = aes(x=bill_length_mm,y=bill_depth_mm))+
  geom_point()

q3="There appears to be three large cluster groupings of observations between bill depth and bill length. A significant linear trend between the observaions does not appear to exist."
#Question 4
ggplot(data = penguins,mapping = aes(x=species,y=bill_depth_mm))+ geom_boxplot()

q4="If I use species within a scatterplot, the obervations will be split into three lines assoicated with each species. A more appropreite geom is the boxplot since it's much easier to see the distribtions of the obersations."
#Question 5
q5="The code has an error since no mapping arguments have been assigned. In order to resolve the issue, we need to adding mapping arguments such as aes(x=bill_length_mm,y=bill_depth_mm)"
#Question 6
ggplot(data = penguins,mapping = aes(x=bill_length_mm,y=bill_depth_mm))+
  geom_point(na.rm = TRUE)

q6="The na.rm argument removes null values from the plot. By default, the argument is set to FALSE."
#Question 7
ggplot(data=penguins, mapping = aes(x=flipper_length_mm,y=body_mass_g)) +
  geom_point(mapping = aes(color=species,shape=species)) +
  geom_smooth(method = "lm")+
  labs(title="Body mass and flipper length",
       subtitle = "Dimensions for Adelie, Chinstrap, and Gentoo Penguins",
       x = "Flipper length (mm)", y="Body mass (g)",
       color="Species",shape="Species",caption = "Data comes from the palmerpenguins package")+
  scale_color_colorblind()

#Question 8
ggplot(data=penguins, mapping = aes(x=flipper_length_mm,y=body_mass_g)) +
  geom_point(mapping = aes(color=bill_depth_mm)) +
  geom_smooth()+
  labs(title="Body mass and flipper length",
       subtitle = "Dimensions for Adelie, Chinstrap, and Gentoo Penguins",
       x = "Flipper length (mm)", y="Body mass (g)",
       color="Species",shape="Species",caption = "Data comes from the palmerpenguins package")

#Question 9
ggplot(data=penguins,mapping=aes(x=flipper_length_mm,y=body_mass_g,color=island))+
  geom_point()+
  geom_smooth(se=FALSE)

#Question 10
ggplot(data = penguins,mapping=aes(x=flipper_length_mm,y=body_mass_g))+
  geom_point()+
  geom_smooth(se=FALSE)


ggplot()+geom_point(data = penguins,mapping=aes(x=flipper_length_mm,y=body_mass_g))+geom_smooth(data=penguins,mapping=aes(x=flipper_length_mm,y=body_mass_g))


q10="These plots will look very similar but the first one will not have a confidence range displayed."
#Remove data and mapping text
ggplot(penguins,aes(x=flipper_length_mm,y=body_mass_g))+geom_point()

#Piping
penguins |>
  ggplot(aes(x=flipper_length_mm,y=body_mass_g)) +
  geom_point()

#Categorical Variables
ggplot(penguins,aes(x=species))+geom_bar()

#Ordering factor
ggplot(penguins,aes(x=fct_infreq(species)))+geom_bar()

#Histogram
ggplot(penguins,aes(x=body_mass_g))+geom_histogram(binwidth = 200)

ggplot(penguins,aes(x=body_mass_g))+geom_density()

# Question 11
ggplot(penguins,aes(y=species))+geom_bar()

q11="The penguin categories are rotated horizontally when using the y aesthetic."
# Question 12
ggplot(penguins,aes(x=species))+geom_bar(fill="red")

q12="The difference between the two plots is that the fill argument changes the bar graph color while the color changes the bar graph border color."
# Question 13
q13="The bins argument determines the number of buckets the histogram will use."
# Question 14
head(diamonds)
ggplot(diamonds,aes(x=carat))+geom_histogram(bins = 15)

q14="I believe the bin size with 15 groupings is the most interesting since we're able to clearly see the distribution."
#Boxplot
ggplot(penguins,aes(x=species,y=body_mass_g))+geom_boxplot()


#Density Plot
ggplot(penguins,aes(x=body_mass_g,color=species,fill=species))+geom_density(alpha=.5)

#Category vs Category
ggplot(penguins,aes(x=island,fill=species))+geom_bar()


ggplot(penguins,aes(x=island,fill=species))+geom_bar(position = "fill")

#Three or More Variables
ggplot(penguins,aes(x=flipper_length_mm,y=body_mass_g))+
  geom_point(aes(color=species,shape=island))+
  facet_wrap(~island)

# Question 15
head(mpg)
q15="manufacturer=categorical, model=categorical, displ=numerical,year=categorical,cyl=categorical,trans=categorical,drv=categorical, cty=numerical, hwy=numerical... I am able to determine these categories by looking at the number of occurancies and background information."
# Question 16
ggplot(mpg,aes(x=hwy,y=displ,size=cty,color=cty,linewidth=cty))+geom_point()

q16="For numerical values a scale is introduced and for categorical values a new color is used for each grouping."
# Question 17
q17="There is no change since line width does not affect a scatter plot"
# Question 18
q18="A variable can be used in several asethetics within visualization. If this occurs, each asethetics will be affested accordingly."
# Question 19
ggplot(data=penguins,mapping = aes(x=bill_length_mm,y=bill_depth_mm,color=species,shape=species))+geom_point()

q19="In order to fix this problem, the arguments within the geom_point function need to be removed."
# Question 20
ggplot(penguins,aes(x=island,fill=species))+
  geom_bar(position="fill")

ggplot(penguins,aes(x=species,fill=island))+
  geom_bar(position="fill")

q20="plot 1 shows the distribution of species on each island while plot 2 shows the distribution of each species with each of the islands."
#ggsave
ggplot(penguins,aes(x=flipper_length_mm,y=body_mass_g))+geom_point()
ggsave(filename="penguin-plot.png")
Saving 7.29 x 4.51 in image

# Question 21
ggplot(mpg,aes(x=class))+
  geom_bar()

ggplot(mpg,aes(x=cty,y=hwy))+
  geom_point()
ggsave("mpg-plot.pdf")
Saving 7.29 x 4.51 in image

q21="The second plot is saved since the ggsave function was run after the second set of plotting code."
# Question 22
q22="To save the plot as a pdf, the file extension would need to be updated to .pdf instead of .png"

Chapter 2: Workflow Basics

#Vector
primes <- c(2,3,5,7,11,13)
primes*2
[1]  4  6 10 14 22 26
this_is_a_really_long_name<-2.5
seq(1,10)
 [1]  1  2  3  4  5  6  7  8  9 10
x<-"hello world"
# Question 23
q23<-"The code does not work because the variable is misspelled"
# Question 24
# library(tidyverse)
# ggplot(dTA,aes(x=displ,y=hwy))+
#   geom_point()+
#   geom_smooth(method="lm")
# Question 25
q25<-"option shift k displays RStudio shortcuts. This can also be viewed from the help menu."
# Question 26
q26<-"The second plot is saved this time since the plot argument specifies the first graph."

Chapter 3: Data Transformation

library(nycflights13)
library(tidyverse)
flights

#Use view to see an entier tibble
View(flights)

#Use to see all columns
glimpse(flights)
Rows: 336,776
Columns: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 201…
$ month          <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ day            <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ dep_time       <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 558, 558, 558, 558, 559, 559, 559, 600, 600, 601, 602, 602, 6…
$ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 600, 600, 600, 600, 600, 559, 600, 600, 600, 600, 610, 605, 6…
$ dep_delay      <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2, -1, 0, -1, 0, 0, 1, -8, -3, -4, -4, 0, 8, 11, 3, 0, 0, -8,…
$ arr_time       <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 849, 853, 924, 923, 941, 702, 854, 851, 837, 844, 812, 821, …
$ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 851, 856, 917, 937, 910, 706, 902, 858, 825, 850, 820, 805, …
$ arr_delay      <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7, -14, 31, -4, -8, -7, 12, -6, -8, 16, -12, -8, -17, 32, 14,…
$ carrier        <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6", "AA", "B6", "B6", "UA", "UA", "AA", "B6", "UA", "B6", "MQ…
$ flight         <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301, 49, 71, 194, 1124, 707, 1806, 1187, 371, 4650, 343, 1919,…
$ tailnum        <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N39463", "N516JB", "N829AS", "N593JB", "N3ALAA", "N793JB", "…
$ origin         <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LGA", "JFK", "LGA", "JFK", "JFK", "JFK", "EWR", "LGA", "JFK",…
$ dest           <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IAD", "MCO", "ORD", "PBI", "TPA", "LAX", "SFO", "DFW", "BOS",…
$ air_time       <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149, 158, 345, 361, 257, 44, 337, 152, 134, 147, 170, 105, 152…
$ distance       <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 733, 1028, 1005, 2475, 2565, 1389, 187, 2227, 1076, 762, 1023…
$ hour           <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, …
$ minute         <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 10, 5, 10, 10, 7, 0, 0, 10, 15, 15, 30, 10, 2…
$ time_hour      <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 06:00:00, 2013-…
#Filter
flights |>
  filter(dest=="IAH") |>
  group_by(year,month,day) |>
  summarise(
    arr_delay = mean(arr_delay,na.rm = TRUE)
  )
`summarise()` has grouped output by 'year', 'month'. You can override using the `.groups` argument.
flights |>
  filter(dep_delay>120)

jan1<-flights |>
  filter(month ==1 & day==1)

flights |>
  filter(month ==1 | month==2)

flights |>
  filter(month %in% c(1,2))

flights |>
  filter(month==1)
NA
#Arrange
flights |>
  arrange(year,month,day,desc(dep_time))
#Distinct
flights |>
  distinct(origin,dest,.keep_all = TRUE)
flights |>
  count(origin,dest,sort=TRUE)

table(flights$carrier)

   9E    AA    AS    B6    DL    EV    F9    FL    HA    MQ    OO    UA    US    VX    WN    YV 
18460 32729   714 54635 48110 54173   685  3260   342 26397    32 58665 20536  5162 12275   601 
# Question 27
flights |>
  filter(arr_delay>=120)

flights |>
  filter(dest %in% c('IAH','HOU'))

flights |>
  filter(carrier %in% c('UA','DL'))

flights |>
  filter(month %in% c(7,8,9))

flights |>
  filter(dep_delay<=0 & arr_delay>=120)

flights |>
  filter(dep_delay>=60 & arr_delay <=30)
NA
# Question 28
flights |>
  arrange(desc(dep_delay))

flights |>
  arrange(desc(dep_delay))

flights |>
  arrange(dep_time)
# Question 29
flights |>
  arrange(air_time)
# Question 30 
q30<-"Yes"
flights |>
  distinct(month,day,.keep_all = TRUE)
# Question 31
flights |>
  arrange(desc(distance))
# Question 32
q32<-"It's important to filter the data first and then perform any arrangements. Removing unneeded data will allow the arrange function to complete must faster since there is less data to evaluate."
# Mutate
flights |>
  mutate(
    gain = dep_delay - arr_delay,
    speed = distance / air_time * 60,
    .before = 2
  )
# Mutate
flights |>
  mutate(
    gain = dep_delay - arr_delay,
    speed = distance / air_time * 60,
    .after = day
  )
# Mutate
flights |>
  mutate(
    gain = dep_delay - arr_delay,
    hours = air_time / 60,
    gain_per_hour = gain / hours,
    .keep = "used"
  )
# Select, rename, relocate
flights |>
  select(year,month,day)

flights |>
  select(year:day)

flights |>
  select(!year:day)

flights |>
  select(where(is.character))

flights |>
  select(tail_num = tailnum)

flights |>
  rename(tail_num = tailnum)

flights |>
  relocate(time_hour,air_time)

flights |>
  relocate(year:dep_time,.after=time_hour)

flights |>
  relocate(starts_with("arr"),.before=dep_time)
# Question 33
q33<-"I would expect these variables to all be related to a plane's depature. Departure delay would represent the time between sched_dep_time and Dep_time."
# Question 34
q34<-"There are a lot of methods but I would use the select function and define each column or I would use the select function and the contains function to find Delay"
# Question 35
flights |>
  select(tailnum,tailnum)

q35<-"If the same column is listed twice, the column will only be pulled in once."
# Question 36
q36<-"The any_of() function helps with selecting data that meets a particular filter critera. Specifically, the functions means select any data from the specified columns that meet a condition. For this example, it would be help because we would be able to select particular flights based upon a specified condition."
# Question 37
flights |> select(contains("TIME"))
q37<-"This function selects any columns that contains the word time regardless of case. If case is important, we could add the ignore.case argument."
#Question 38
flights |>
  select(air_time_min=air_time)
# Question 39
q39<-"The code results in an error since arr_delay was not selected within the select function."
#Example
flights |>
  filter(dest=="IAH") |>
  mutate(speed = distance / air_time * 60) |>
  arrange(desc(speed))
#Group By
flights |>
  group_by(month)

flights |> 
  group_by(month) |> 
  summarise(
    avg_delay = mean(dep_delay,na.rm = TRUE),
    n=n()
  )
flights |> 
  group_by(dest) |> 
  slice_max(arr_delay,n=1,with_ties = FALSE) |> 
  relocate(dest)
daily<-flights |> 
  group_by(year,month,day)
daily |>
  summarise(
    n=n(),
    .groups="drop_last"
  )

daily |>
  summarise(
    n=n(),
    .groups="drop"
  )

daily |> 
  ungroup()

daily |>
  ungroup() |> 
  summarise(
    avg_delay = mean(dep_delay,na.rm=TRUE),
    flights=n()
  )

flights |>
  summarise(
    delay = mean(dep_delay,na.rm=TRUE),
    n=n(),
    .by=c(origin,dest)
  )
options(scipen = 999)
# Question 40
flights |> 
  group_by(carrier,dest) |> 
  summarise(delay = sum(dep_delay,na.rm=TRUE),n=n()) |> 
  mutate(avg_delay=delay/n) |>
  arrange(desc(avg_delay))
`summarise()` has grouped output by 'carrier'. You can override using the `.groups` argument.
flights |> 
  group_by(carrier) |>
  summarise(delay=mean(dep_delay+arr_delay,na.rm = TRUE)) |> 
  arrange(desc(delay))
# Question 41
flights |> 
  group_by(dest) |> 
  slice_max(arr_delay,n=1,with_ties = TRUE) |> 
  arrange(desc(dep_delay))
# Question 42
flights |> 
  group_by(dep_time) |> 
  summarise(mean_delay=mean(arr_delay,na.rm = TRUE)) |> 
  ggplot(aes(x=dep_time,y=mean_delay))+
  geom_line()


q42<-"The delays appears to decrease significantly after the morning."
# Question 43
q43<-"If a negative value is introduced, all rows within the tibble will be displayed."
# Question 44
q44<-"The count function displays the number of unique values. The count values can then by sorted by the arrange function. In addition, the sort attribute can be used to arrange the count values."
# Question 45
df <- tibble(
  x=1:5,
  y=c("a","b","a","a","b"),
  z=c("K","K","L","L","K")
)

 df |> 
   group_by(y)
 
 q45<-"There is visually no changes but the tibble is now grouped by the y variable."
# Question 46
df |>
  arrange(y)
q46<-"The tibble is sorted alphabetically on the y variable"
# Question 47
df |> 
  group_by(y) |> 
  summarise(mean_x=mean(x))
q47<-"The tibble is grouped by variable y and is then a mean summarize function is called."
# Question 48
df |> 
  group_by(y,z) |> 
  summarise(mean_x=mean(x),.groups = "drop")
q48<-"The unique y and z variable combinations are summarized by taking the mean mean of x."
# Question 49
df |> 
  group_by(y,z) |> 
  summarise(mean_x=mean(x))
`summarise()` has grouped output by 'y'. You can override using the `.groups` argument.
df |> 
  group_by(y,z) |> 
  mutate(mean_x = mean(x))

q49<-"The difference between these two pipelines is that the first one summarizes with the mean function and the second one adds a new column based upon the mean of x."

Chapter 4: Workflow Code Style

library(styler)
library(tidyverse)
library(nycflights13)
#Command + Shift + P
#stive for
#z <- (a + b)^2 / d

#avoid
#z<-( a + b ) ^ 2/d

#cmd + shift + R 
# Question 50
flights |>
  filter(dest=="IAH") |>
  group_by(year,month,day) |> 
  summarise(
    n=n(),
    delay=mean(arr_delay,
    na.rm=TRUE)) |> 
  filter(n>10) 
`summarise()` has grouped output by 'year', 'month'. You can override using the `.groups` argument.
flights |> 
  filter(
    carrier=="UA",
    dest%in%c("IAH","HOU"),
    sched_dep_time>0900,
    sched_arr_time<2000) |> 
  group_by(flight) |> 
  summarise(delay=mean(arr_delay,na.rm = TRUE),cancelled=sum(is.na(arr_delay)),n=n()) |> 
  filter(n>10)

Chapter 4: Workflow Code Style

library(tidyverse)
#Question 51
#Table 1
q51=c(t1,t2,t3)
Error: object 't1' not found
#Question 52
q52<-"In order to properly get the mutation results I would have to split the tables apart / use a regular regression and then join the tables back to each other by country."
#pivot_longer() / pivot_wider()
billboard

billboard |> 
  pivot_longer(
    col=starts_with("wk"),
    names_to = "week",
    values_to = "rank",
    values_drop_na = TRUE
  ) |> 
  mutate(
    week = parse_number(week)
  )
billboard |> 
  pivot_longer(
    col=starts_with("wk"),
    names_to = "week",
    values_to = "rank",
    values_drop_na = TRUE
  ) |> 
  mutate(
    week = parse_number(week)
  ) |> 
  ggplot(aes(x=week,y=rank,group=track))+
  geom_line(alpha=0.25)+
  scale_y_reverse()
df <- tribble(
  ~id, ~bp1, ~bp2,
  "A", 100, 120,
  "B", 140, 115,
  "C", 120, 125
)
df |> 
  pivot_longer(
    cols = bp1:bp2,
    names_to = "measurement",
    values_to = "value"
  )
who2 |> 
  pivot_longer(
    cols = !(country:year),
    names_to = c("diagnosis","gender","age"),
    names_sep = "_",
    values_to = "count"
  )
household |> 
  pivot_longer(
    cols = !family,
    names_to = c(".value","child"),
    names_sep = "_",
    values_drop_na = TRUE
  )
#Pivot Wider
cms_patient_experience

cms_patient_experience |> 
  distinct(measure_cd,measure_title)

cms_patient_experience |> 
  pivot_wider(
    id_cols=starts_with("org"),
    names_from = measure_cd,
    values_from = prf_rate
  )
df <- tribble(
  ~id,~measurement,~value,
  "A", "bp1", 100,
  "B", "bp1", 140,
  "B", "bp2", 115,
  "A", "bp2", 120,
  "A", "bp3", 105
)

df |> 
  pivot_wider(
    names_from = measurement,
    values_from = value
  )

df |> 
  distinct(measurement) |> 
  pull()

df |> 
  select(-measurement,-value) |> 
  distinct()

                                                                                                  

Chapter 6: Workflow: Scripts and Projects

usethis::use_blank_slate()
getwd()
library(tidyverse)
library(ggplot2)
library(caret)

ggplot(diamonds,aes(x=carat,y=price))+
  geom_hex()
ggsave("diamonds.png")
library(tidyverse)
library(janitor)
students<-read_csv("https://pos.it/r4ds-students-csv")

students

students<-read_csv("https://pos.it/r4ds-students-csv",na=c("N/A",""))

students <- students |>
  rename(student_id = `Student ID`,
         full_name = `Full Name`)

students <- students |>
  janitor::clean_names() |>
  mutate(meal_plan = factor(meal_plan),
         age = parse_number(if_else(age == "five", "5", age)))
         
read_csv("The first line of metadata
          The second line of meta daat
          a,b,c
          1,2,3
          4,5,6",
          skip=2)

read_csv(
  "# A comment I want to skip
  x,y,z
  1,2,3",
  comment="#"
)

read_csv(
  "1,2,3
   4,5,6",col_names= FALSE)

read_csv(
  "1,2,3
   4,5,6",col_names= c("x","y","z"))
#Question 53
q53<-"I would use the read_delim() function to pull in data that is separated with the | symbol."
#Question 54
q54<-"read_csv() and read_tsv() share many arguments. Specifically they share col_names, col_types, id etc..."
#Question 55
q55<-"The most important argument for read_fwf() is the widths() function since the field size must be specified."
#Question 56
library(readr)

q56 <- read_csv("x,y\n1,'a,b'", quote = "'")
#Question 57
read_csv("a,b/n 
          12,3/n 
          4,5,6")

read_csv("a,b,c/n
          1,2/n
          1,2,3,4")

read_csv("a,b\n1")

read_csv('a,b\n"1,2",3\na,b')

read_csv2("a;\n1;3")
#Question 58
annoying <- tibble(
  '1' = 1:10,
  '2' = as.numeric('1') * 2 + rnorm(10)
)

annoying |> 
  select(1)

annoying |> 
  ggplot(aes(x=`1`,y=`2`))+
  geom_point()

annoying <- annoying |>
  mutate(`3` = `2` / `1`)

annoying |> 
  rename(`One`=`1`,
         `Two`=`2`,
         `Three`=`3`)
read_csv("
         logical.numeric,date,string
         TRUE,1,2021-01-15,abc
         false,4.5,2021-02-15,def
         T,Inf,2021-02-16,ghi")
simple_csv <- "
x
10
.
20
30"

df<-read_csv(
  simple_csv,
  col_types = list(x=col_double()))

problems(df)

read_csv(
  simple_csv,na=".")
another_csv <- "
x,y,z
1,2,3"

read_csv(
  another_csv,
  col_types = cols(.default=col_character())
)

read_csv(
  another_csv,
  col_types = cols_only(x=col_character())
)
sales_files <- c(
  "https://pos.it/r4ds-01-sales",
  "https://pos.it/r4ds-02-sales",
  "https://pos.it/r4ds-03-sales"
)
read_csv(sales_files,id="file")

sales_files <- list.files("data",pattern = "sales\\.csv$",full.names = TRUE)
sales_files
write_csv(students,"students.csv")
write_rds(students,"students.rds")
read_rds("students.rds")
library(arrow)
write_parquet(students,"students.parquet")
read_parquet("students.parquet")
#Data Entry
tibble(
  x=c(1,2,5),
  y=c("h","m","g"),
  z=c(0.08,0.83,0.60)
)

tribble(
  ~x,~y,~z,
  1,"h",0.08,
  2,"m",0.83,
  5,"g",0.60
)

Chapter 8: Workflow Getting Help

y<-1:4
mean(y)
library(reprex())
y<- 1:4
mean(y)

reprex(mtcars)
tidyverse_update()
dput(mtcars)
structure(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1, 14.3, 
24.4, 22.8, 19.2, 17.8, 16.4, 17.3, 15.2, 10.4, 10.4, 14.7, 32.4, 
30.4, 33.9, 21.5, 15.5, 15.2, 13.3, 19.2, 27.3, 26, 30.4, 15.8, 
19.7, 15, 21.4), cyl = c(6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 
8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4), 
    disp = c(160, 160, 108, 258, 360, 225, 360, 146.7, 140.8, 
    167.6, 167.6, 275.8, 275.8, 275.8, 472, 460, 440, 78.7, 75.7, 
    71.1, 120.1, 318, 304, 350, 400, 79, 120.3, 95.1, 351, 145, 
    301, 121), hp = c(110, 110, 93, 110, 175, 105, 245, 62, 95, 
    123, 123, 180, 180, 180, 205, 215, 230, 66, 52, 65, 97, 150, 
    150, 245, 175, 66, 91, 113, 264, 175, 335, 109), drat = c(3.9, 
    3.9, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92, 
    3.07, 3.07, 3.07, 2.93, 3, 3.23, 4.08, 4.93, 4.22, 3.7, 2.76, 
    3.15, 3.73, 3.08, 4.08, 4.43, 3.77, 4.22, 3.62, 3.54, 4.11
    ), wt = c(2.62, 2.875, 2.32, 3.215, 3.44, 3.46, 3.57, 3.19, 
    3.15, 3.44, 3.44, 4.07, 3.73, 3.78, 5.25, 5.424, 5.345, 2.2, 
    1.615, 1.835, 2.465, 3.52, 3.435, 3.84, 3.845, 1.935, 2.14, 
    1.513, 3.17, 2.77, 3.57, 2.78), qsec = c(16.46, 17.02, 18.61, 
    19.44, 17.02, 20.22, 15.84, 20, 22.9, 18.3, 18.9, 17.4, 17.6, 
    18, 17.98, 17.82, 17.42, 19.47, 18.52, 19.9, 20.01, 16.87, 
    17.3, 15.41, 17.05, 18.9, 16.7, 16.9, 14.5, 15.5, 14.6, 18.6
    ), vs = c(0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 
    0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1), am = c(1, 
    1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), gear = c(4, 4, 4, 3, 
    3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 
    3, 3, 4, 5, 5, 5, 5, 5, 4), carb = c(4, 4, 1, 1, 2, 1, 4, 
    2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 
    2, 2, 4, 6, 8, 2)), row.names = c("Mazda RX4", "Mazda RX4 Wag", 
"Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", 
"Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", 
"Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", 
"Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", 
"Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", 
"Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", 
"Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", 
"Volvo 142E"), class = "data.frame")
reprex(mtcars<-structure(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1, 14.3, 
24.4, 22.8, 19.2, 17.8, 16.4, 17.3, 15.2, 10.4, 10.4, 14.7, 32.4, 
30.4, 33.9, 21.5, 15.5, 15.2, 13.3, 19.2, 27.3, 26, 30.4, 15.8, 
19.7, 15, 21.4), cyl = c(6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 
8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4), 
    disp = c(160, 160, 108, 258, 360, 225, 360, 146.7, 140.8, 
    167.6, 167.6, 275.8, 275.8, 275.8, 472, 460, 440, 78.7, 75.7, 
    71.1, 120.1, 318, 304, 350, 400, 79, 120.3, 95.1, 351, 145, 
    301, 121), hp = c(110, 110, 93, 110, 175, 105, 245, 62, 95, 
    123, 123, 180, 180, 180, 205, 215, 230, 66, 52, 65, 97, 150, 
    150, 245, 175, 66, 91, 113, 264, 175, 335, 109), drat = c(3.9, 
    3.9, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92, 
    3.07, 3.07, 3.07, 2.93, 3, 3.23, 4.08, 4.93, 4.22, 3.7, 2.76, 
    3.15, 3.73, 3.08, 4.08, 4.43, 3.77, 4.22, 3.62, 3.54, 4.11
    ), wt = c(2.62, 2.875, 2.32, 3.215, 3.44, 3.46, 3.57, 3.19, 
    3.15, 3.44, 3.44, 4.07, 3.73, 3.78, 5.25, 5.424, 5.345, 2.2, 
    1.615, 1.835, 2.465, 3.52, 3.435, 3.84, 3.845, 1.935, 2.14, 
    1.513, 3.17, 2.77, 3.57, 2.78), qsec = c(16.46, 17.02, 18.61, 
    19.44, 17.02, 20.22, 15.84, 20, 22.9, 18.3, 18.9, 17.4, 17.6, 
    18, 17.98, 17.82, 17.42, 19.47, 18.52, 19.9, 20.01, 16.87, 
    17.3, 15.41, 17.05, 18.9, 16.7, 16.9, 14.5, 15.5, 14.6, 18.6
    ), vs = c(0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 
    0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1), am = c(1, 
    1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1), gear = c(4, 4, 4, 3, 
    3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 
    3, 3, 4, 5, 5, 5, 5, 5, 4), carb = c(4, 4, 1, 1, 2, 1, 4, 
    2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 
    2, 2, 4, 6, 8, 2)), row.names = c("Mazda RX4", "Mazda RX4 Wag", 
"Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", 
"Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", 
"Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", 
"Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", 
"Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", 
"Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", 
"Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", 
"Volvo 142E"), class = "data.frame"))

Part 2: Visualize

Chapter 9: Layers

library(tidyverse)
mpg
ggplot(mpg,aes(x=displ,y=hwy,color=class))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy,shape=class))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy,size=class))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy,alpha=class))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(color="blue")

# Question 60
#ggplot(mpg,aes(color='blue')) + geom_point(aes(x=displ,y=hwy))
ggplot(mpg,aes(x=displ,y=hwy,color='pink'))+geom_point(color='blue')

q60<-"The points are not blue because the x and y need to be defined within the ggplot() function call and the color needs to be defined within the geom_point() function."
# Question 61
q61<-"The stroke aesthetic determines the thickness of the visual attribute. The most common geoms are scatterplots, line plots, and bar charts."
# Question 62
ggplot(mpg,aes(x=displ,y=hwy,color='pink'))+geom_point(color=mpg$displ)

q62<-"If an aesthetic is mapped to something that is not a variable, then an error will occur."
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy))+
  geom_smooth()+
  geom_point()

ggplot(mpg,aes(x=displ,y=hwy,shape=drv))+
  geom_smooth()


ggplot(mpg,aes(x=displ,y=hwy,linetype=drv))+
  geom_smooth()

ggplot(mpg,aes(x=displ,y=hwy,color=drv))+
  geom_point()+
  geom_smooth(aes(linetype=drv))

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()+
  geom_point(
    data = mpg |> 
      filter(class=="2seater"),
    shape="circle open",size=3,color="red"
  )

ggplot(mpg,aes(x=hwy))+
  geom_histogram(binwidth = 2)


ggplot(mpg,aes(x=hwy))+
  geom_density()


ggplot(mpg,aes(x=hwy))+
  geom_boxplot()

NA
NA

# Question 63
q63<-"geom_line(), geom_boxplot(), geom_histogram(), geom_area()"
# Question 64
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_smooth(aes(color=drv))

q64<-"The legend arguement determine if a legend should be added to the graph. If I remove it, the legend is added back in. We used this earlier since we more focused on the splitting the data into the three drv groups."
# Question 65
q65<-"The se argument determines if a confidence interval should be added."
#Question 66
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()+
  geom_smooth(se=FALSE)

ggplot(mpg,aes(x=displ,y=hwy,shape=drv))+
  geom_point()+
  geom_smooth(se=FALSE)

ggplot(mpg,aes(x=displ,y=hwy,color=drv))+
  geom_point()+
  geom_smooth(se=FALSE)

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(aes(color=drv))+
  geom_smooth(se=FALSE)

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(aes(color=drv))+
  geom_smooth(se=FALSE,aes(linetype=drv))

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(aes(color=drv,fill='white'),fill='white')+
  geom_point(shape=1,color='white',size=3,stroke=2)
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()+
  facet_grid(drv~cyl,scales="free_y")
# Question 66
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()+
  facet_wrap(~cty)
q66<-"Faceting a continious variable will make a visual for each unique value"
# Question 67
ggplot(mpg)+
  geom_point(aes(x=displ,y=cyl))+
  facet_grid(drv~cyl)

q67<-"The empty charts represent value combinations that don't exist between the two variables."
# Question 68
ggplot(mpg) +
  geom_point(aes(x=displ,y=hwy))+
  facet_grid(drv~.)


ggplot(mpg)+
  geom_point(aes(x=displ,y=hwy))+
  facet_grid(cyl~.)


q68<-"These plots facet by drv and cyl. The . position relative to ~ determines the plot orientation."
# Question 69
ggplot(mpg)+
  geom_point(aes(x=displ,y=hwy))+
  facet_wrap(~class,nrow=2)
q69<-"One advantage of faceting is that it's easier to evaluate each grouping. The disdvantage is that it's harder to compare between groups. If we have a very large dataset, faceting would be the best option since will be able to split the data into small groupings."
# Question 70
q70<-"nrow determines the number of rows, ncols determines the number of columns. Additional options include scales, labeller etc. facet_grid() doesn't need the rows or columns argument because we are faceting of continious variables."
#Question 71
ggplot(mpg,aes(x=displ))+
  geom_histogram()+
  facet_grid(drv~.)

ggplot(mpg,aes(x=displ))+
  geom_histogram()+
  facet_grid(.~drv)

q71<-"The first plot is easier to read because each plot shares the same x-axis range / the plots are stacked on top of each other. It's much harder to compare the plots when they are side by side."
q72<-"When switchign from facet wrap to facet grid, the graph orientation changes from horizontal to vertical."

<!-- rnb-source-end -->

<!-- rnb-output-begin eyJkYXRhIjoiRXJyb3I6IGF0dGVtcHQgdG8gdXNlIHplcm8tbGVuZ3RoIHZhcmlhYmxlIG5hbWVcbiJ9 -->

Error: attempt to use zero-length variable name




<!-- rnb-output-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWN1dCkpK2dlb21fYmFyKClcblxuZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWN1dCx5PWFmdGVyX3N0YXQocHJvcCksZ3JvdXA9MSkpK2dlb21fYmFyKClcblxuZ2dwbG90KGRpYW1vbmRzKSArXG4gIHN0YXRfc3VtbWFyeShcbiAgICBhZXMoeD1jdXQsIHk9ZGVwdGgpLFxuICAgIGZ1bi5taW49bWluLGZ1bi5tYXg9bWF4LFxuICAgIGZ1bj1tZWRpYW5cbiAgKVxuYGBgIn0= -->

```r
ggplot(diamonds,aes(x=cut))+geom_bar()

ggplot(diamonds,aes(x=cut,y=after_stat(prop),group=1))+geom_bar()

ggplot(diamonds) +
  stat_summary(
    aes(x=cut, y=depth),
    fun.min=min,fun.max=max,
    fun=median
  )

#Question 75
q75<-"The difference between geom_col() and geom_bar() is that geom_col() is used when both x and y asethetics are known and geom_bar() is used typically when only the x asethetic is known."
# Question 76
q76<-"Some of the common pairs are scatterplots (geom_point, stat_identity), line charts (geom_line, stat_identity), and Bar Charts (geom_bar(), stat_count)"
# Question 77
q77<-"stat_smooth calculates fitted values from a regression model that uses the x and y variables. Some common arguments include the regression type, formula, confidence interval, or distribution family."
#Question 78
ggplot(diamonds,aes(x=cut,y=after_stat(prop)))+
  geom_bar()

ggplot(diamonds,aes(x=cut,fill=color,y=after_stat(prop)))+
  geom_bar()

q78<-"The group argument in proportion plots must be specified so that the proportion is calculated properly when considering each category. If the group is not specified, the graph will incorrectly calcuate the proportion."
ggplot(mpg,aes(x=drv,color=drv))+
  geom_bar()


ggplot(mpg,aes(x=drv,fill=drv))+
  geom_bar()


ggplot(mpg,aes(x=drv,fill=class))+
  geom_bar()


ggplot(mpg,aes(x=drv,fill=class))+
  geom_bar(alpha=1/5,position="identity")


ggplot(mpg,aes(x=drv,color=class))+
  geom_bar(fill=NA,position = "identity")


ggplot(mpg,aes(x=drv,fill=class))+
  geom_bar(position = "fill")


ggplot(mpg,aes(x=drv,fill=class))+
  geom_bar(position = "dodge")

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(position="jitter")

#Question 79
q79<-"These plots produce the same chart. The position=identity argument plots the points the same way as the default setting." 
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()


ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point(position="identity")

#Question 80
q80<-"The width and height parameters control the amount of jittering."
#Question 81
q81<-"Geom count creates an asethetic based upon point size while geom jitter creates an asethetic that slight randomness to the points."
ggplot(mpg,aes(x=displ,y=hwy))+
  geom_count()

#Question 81
q81<-"The default position is dodge2 which plots each box and whisker plot next to each other."
ggplot(mpg,aes(x=displ,y=drv))+
  geom_boxplot(position="dodge")
nz<-map_data("nz")

ggplot(nz,aes(x=long,y=lat,group=group))+
  geom_polygon(fill="white",color="black")


ggplot(nz,aes(x=long,y=lat,group=group))+
  geom_polygon(fill="white",color="black")+
  coord_quickmap()


bar <- ggplot(data=diamonds)+
  geom_bar(
    mapping=aes(x=clarity,fill=clarity),
    show.legend = FALSE,
    width = 1
  ) +
  theme(aspect.ratio = 1)

bar + coord_flip()

bar + coord_polar()

#Question 82
q82<-"The difference between the coord_quickmap() and coord_map() is that coord_quickmap() is a coordniate system that provides a good projection quickly for x and y coordinates while the coord_map() function uses the mercator projection."
#Question 83
q83<-ggplot(data=mpg,mapping=aes(x=cty,y=hwy))+
  geom_point()+
  geom_abline()+
  coord_fixed()
q83<-"From this plot, we can see that hwy mpg is always high than city mpg. The coord_fixed function ensures that the x-axis and y-axis has the same coordinate scale. The geom_abline addes a 45 degree angle that helps add perspective. "

Chapter 10: Exploritory Data Analysis

library(tidyverse)
ggplot(diamonds,aes(x=carat))+
  geom_histogram(bins=10)

smaller <- diamonds |> 
              filter(carat<3)

ggplot(smaller,aes(x=carat))+
  geom_histogram(binwidth =.01)
ggplot(diamonds,aes(x=y))+
  geom_histogram(binwidth=0.5)

ggplot(diamonds,aes(x=y))+
  geom_histogram(binwidth=0.5)+
  coord_cartesian(ylim=c(0,50))

unusual <- diamonds |> 
  filter(y<3 | y>20) |> 
  select(price,x,y,z) |> 
  arrange(y)
#Question 83
ggplot(diamonds,aes(x=x))+
  geom_histogram()

ggplot(diamonds,aes(x=y))+
  geom_histogram()

ggplot(diamonds,aes(x=z))+
  geom_histogram()

q83<-"By looking at the distribution of the x,y and z variables, I can see that y and z have similar distribution while x has a wide range between 3-9. I believe that y and z is the length and width since diamonds are typically round and x is the depth which we would expect to have some variation."
#Question 84
ggplot(diamonds,aes(x=price))+
  geom_histogram(binwidth = 250)

q84<-"By looking at the price distribution, we can see that the majority of diamonds have prices that are less than 5,000 dollars. In addition, the distribution seemes to be skewed to the left. I find it suprising that the count frequency decreases gradually after 5,000 dollars."
#Question 85
diamonds |> 
  filter(carat==0.99) |> 
  summarise(count=n())

diamonds |> 
  filter(carat==1) |> 
  summarise(count=n())

q85<-"There are 23 diamonds that are 0.99 carat and 1558 diamonds that are 1 carat. I believe this is due to variation within diamonds cuts. In addition, I believe 1 carat diamonds are a common selection."
# Question 86
q86<-"coord_cartesian() is different than xlim() and ylim() because coord_cartesian() zooms in on the ggplot while xlim and ylim filter the underlaying dataset. The outcome is similar since both function are limiting the visable range. If the binwidth function is not set, then R will find an appropriate bin width. If the objective is to only see half a bar, then coord_cartesian() is the recommended function. The ylim() or xlim() will not work because it will filter out the whole bar."
diamonds2<-diamonds |> 
  filter(between(y,3,20))

diamonds2<-diamonds |> 
  mutate(y=if_else(y<3 | y>20,NA,y))

ggplot(diamonds2,aes(x=x,y=y))+
  geom_point(na.rm = TRUE)
nycflights13::flights |> 
  mutate(
    cancelled = is.na(dep_time),
    sched_hour = sched_dep_time %/% 100,
    sched_min = sched_dep_time %% 100,
    sched_dep_time = sched_hour + (sched_min/60)
  ) |> 
  ggplot(aes(x=sched_dep_time))+
  geom_freqpoly(aes(color=cancelled,bindwith=1/4))
Warning: Ignoring unknown aesthetics: bindwith

# Question 87
q87<-"Histograms will ignore NA values while bar charts include NA values. Histograms exclude them since they deal primarily with counts while bar charts usually involve categories. In this case we would not want to count NA values in counts but include them as a category."
# Question 88
q88<-"na.rm is an argument that allows for values to be either included or removed with the mean() or sum() functions."
# Question 89
nycflights13::flights |> 
  mutate(
    cancelled = is.na(dep_time),
    sched_hour = sched_dep_time %/% 100,
    sched_min = sched_dep_time %% 100,
    sched_dep_time = sched_hour + (sched_min/60)
  ) |> 
  ggplot(aes(x=sched_dep_time))+
  geom_freqpoly(aes(color=cancelled,bindwith=1/4))+
  facet_wrap(~cancelled,scales = "fixed")
ggplot(diamonds,aes(x=price))+
  geom_freqpoly(aes(color=cut),binwidth=300,linewidth=0.75)

ggplot(diamonds,aes(x=price,y=after_stat(density)))+
  geom_freqpoly(aes(color=cut),binwidth=500,linewidth=0.75)

ggplot(diamonds,aes(x=cut,y=price))+
  geom_boxplot()

ggplot(mpg,aes(x=class,y=hwy))+
  geom_boxplot()


ggplot(mpg,aes(x=fct_reorder(class,hwy,median),y=hwy))+
  geom_boxplot()


ggplot(mpg,aes(y=fct_reorder(class,hwy,median),x=hwy))+
  geom_boxplot()

# Question 90
nycflights13::flights |> 
  mutate(
    cancelled = is.na(dep_time),
    sched_hour = sched_dep_time %/% 100,
    sched_min = sched_dep_time %% 100,
    sched_dep_time = sched_hour + (sched_min/60)
  ) |> 
  ggplot(aes(x=sched_dep_time,y=after_stat(density)))+
  geom_freqpoly(aes(color=cancelled,bindwith=1/4))
# Question 91
library(corrplot)
summary(lm(data=diamonds,price~.))
nd<-diamonds |> 
  select_if(is.numeric)
m<-cor(nd)
corrplot(m)

ggplot(diamonds,aes(x=price,y=after_stat(density)))+
  geom_freqpoly(aes(color=cut),binwidth=500,linewidth=0.75)

q91<-"According to my correlation plot, it appears that the x, y, and z variables may be significant in predicting diamond price. It appears that the ideal cuts seem to be more affordiable than the other cuts. I believe that the combination of these two findings show that the diamond size is more significant than the quality of the cut."
# Question 92
ggplot(mpg,aes(x=fct_reorder(class,hwy,median),y=hwy))+
  geom_boxplot()

ggplot(mpg,aes(x=fct_reorder(class,hwy,median),y=hwy))+
  geom_boxplot()+
  coord_flip()
q92<-"It appears that the coord_flip() function performs the same action as switching the x and y arguments."
library(ggplot2)
# Question 93
library(lvplot)
ggplot(diamonds,aes(x=fct_reorder(cut,price,median),y=price))+
  geom_boxplot()+
  coord_flip()


ggplot(diamonds,aes(x=fct_reorder(cut,price,median),y=price))+
  geom_lv()+
  coord_flip()


q93<-"I learned from the letter value plot that box plots often do not tell the full story of the data. In this example, the cuts have a lot of outliers. By using the letter value plot, it's much easier to see the distribution of the price among the various cut categories. To interpret this viaual, one must understand that each letter represents a percentile range that decreases by half for each letter when starting from the center. As you can see, the majority of diamonds are under $2,500."
# Question 94
ggplot(diamonds,aes(x=fct_reorder(cut,price,median),y=price))+
  geom_violin()+
  coord_flip()

ggplot(diamonds,aes(x=price))+
  geom_histogram()+
  coord_flip()+
  facet_wrap(~cut)

ggplot(diamonds,aes(x=price))+
  geom_freqpoly(aes(color=cut),binwidth=500,linewidth=0.75)

ggplot(diamonds,aes(x=price,y=after_stat(density)))+
  geom_freqpoly(aes(color=cut),binwidth=500,linewidth=0.75)

q94<-"The violin plot is great for seeing distribution shape but lacks median or percentile markings. The faceted histogram is create to compare grouops but struggles when a particular group has a few number of values. The two frequency plots are create for comparising distribution shape and density but lacks the ability to see groupings."
# Question 95
library(ggbeeswarm)
 ggplot2::ggplot(ggplot2::mpg,aes(class, hwy)) + geom_beeswarm()
  ggplot2::ggplot(ggplot2::mpg,aes(class, hwy)) + geom_quasirandom()
 ggplot2::ggplot(ggplot2::mpg,aes(class, hwy)) + geom_point()
 q95<-"The two main functions of ggbeeswarm are geom_swarm and quasirandom. ggbeeswarm aligns the points in a violin shape while the quasirandom function shows the points in a violin shape along with added randomness."
 
ggplot(diamonds,aes(x=cut,y=color))+
  geom_count()

diamonds |> 
  count(color,cut)

diamonds |> 
  count(color,cut) |> 
  ggplot(aes(x=color,y=cut))+
  geom_tile(aes(fill=n))
# Question 95
q95<-"I could facet the last plot in order to more clearly show the distribution of cut within color or color within cut."
# Question 96
ggplot(diamonds, aes(x = color, fill = cut)) +
  geom_bar(position = "stack") +
  labs(title = "Segmented Bar Chart of Diamonds",
       x = "color",
       y = "Count",
       fill = "cut")
q96<-"It is much easier to see the difference in color count when switching the x and y axis."
# Question 97
flights<-nycflights13::flights

nycflights13::flights |>
  filter(dest=="ORD" | dest=="IAH") |> 
  group_by(dest,month) |> 
  summarise(AFD=mean(dep_delay,na.rm=TRUE,.groups="drop")) |> 
  ggplot(aes(x=dest,y=month,fill=AFD))+
  geom_tile()
q97<-"The plot is hard to read because there is too many categories being comparied. I can improve this plot by taking a subset of dest and then faceting."
ggplot(smaller,aes(x=carat,y=price))+
  geom_point(alpha=1/100)

# Question 98
q98<-"cut width creates bins based on width specification and cut number creates n number of bins."
# Question 99
ggplot(diamonds, aes(x = carat, y = price, color = price)) +
  geom_point(alpha = 0.7) +
  scale_color_gradient(low = "blue", high = "red") +
  labs(title = "Distribution of Carat Partitioned by Price",
       x = "Carat",
       y = "Price",
       color = "Price Level")


ggplot(smaller,aes(x=carat,y=price)) +
  geom_boxplot(aes(group=cut_interval(carat,10)),varwidth = FALSE)

# Question 101
ggplot(smaller,aes(x=carat,y=price)) +
  geom_boxplot(aes(group=cut_interval(carat,10)),varwidth = TRUE)+
  facet_wrap(~cut)

# Question 103
ggplot(smaller,aes(x=carat,y=price))+
  geom_boxplot(aes(group=cut_number(carat,10)))
q103<-"The advantage of this approach is that we can easily see the distribtion based on the number of observations but it's not clear what the grouping ranges are. "
library(tidymodels)

diamonds <- diamonds |> 
  mutate(
    log_price = log(price),
    log_carat = log(carat)
  )
  
diamonds_fit <- linear_reg() |> 
  fit(log_price ~ log_carat, data = diamonds)

diamonds_aug <- augment(diamonds_fit, new_data = diamonds) |> 
  mutate(.resid=exp(.resid))

ggplot(diamonds_aug,aes(x=carat,y=.resid))+
  geom_point()

Chapter 11: Communication

library(scales)
library(ggrepel)
library(patchwork)

# Question 104
ggplot(mpg,aes(x=cty,y=hwy,color=drv,shape=drv))+
  geom_point()+
  labs(y="Highway MPG",x="City MPG",color="Type of drive train",shape="Type of drive train")
# Question 105
library(palmerpenguins)
library(lvplot)
penguins
ggplot(penguins,aes(x=island,y=bill_length_mm,fill=island))+
  geom_lv()+
  labs(title="Biscoe Island has the longest Bill Length",caption="Palmer Penguins Package",x="Island",y="Bill Length",fill="Island")
label_info <- mpg |> 
  group_by(drv) |> 
  arrange(desc(displ)) |> 
  slice_head(n=1) |> 
  mutate(
    drive_type=case_when(
      drv == "f" ~ "front-wheel drive",
      drv == "r" ~ "rear-wheel drive",
      drv == "4" ~ "4-wheel drive"
    )
  ) |> 
  select(displ,hwy,drv,drive_type)

label_info
ggplot(mpg,aes(x=displ,y=hwy,color=drv))+
  geom_point(alpha=0.3) +
  geom_smooth(se=FALSE)+
  geom_text(
    data = label_info,
    aes(x=displ,y=hwy,label=drive_type),
    fontface = "bold",size=5,hjust="right",vjust="bottom"
  )+
  theme(legend.position="none")

ggplot(mpg,aes(x=displ,y=hwy,color=drv))+
  geom_point()+
  geom_smooth(se=FALSE)+
  geom_label_repel(
    data=label_info,
    aes(x=displ,y=hwy,label=drive_type),
    fontface="bold",size=4,nudge_y=2
  )+
  theme(legend.position = "none")

potential_outliers <- mpg |>
  filter(hwy > 40 | (hwy > 20 & displ > 5))
  
ggplot(mpg, aes(x=displ,y=hwy))+
  geom_point()+
  geom_text_repel(data=potential_outliers,aes(label=model))+
  geom_point(data=potential_outliers,color="red")+
  geom_point(data=potential_outliers, color = "red",size=3,shape="circle open")
trend_text <- "Larger engine sizes tend to\nhave lower fuel economy." |> 
  str_wrap(width=30)

ggplot(mpg,aes(x=displ,y=hwy))+
  geom_point()+
  annotate(
    geom="label",x=3.5,y=38,
    label = trend_text,
    hjust="left",color="red"
  )+
  annotate(
    geom="segment",
    x=3,y=35,xend=5,yend=25,color="red",
    arrow=arrow(type="closed")
  )
LS0tCnRpdGxlOiAiUiBmb3IgRGF0YSBTY2llbmNlIgphdXRob3I6ICJBbGVjIFdpY2siCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIFBhcnQgMTogV2hvbGUgR2FtZSAKIyBDaGFwdGVyIDE6IFZpc3VhbGl6YXRpb24KYGBge3J9CiNMb2FkaW5nIG5lZWRlZCBsaWJyYXJpZXMKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGFsbWVycGVuZ3VpbnMpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsdnBsb3QpCmxpYnJhcnkoZ2diZWVzd2FybSkKYGBgCgpgYGB7cn0KI0RpZmZlcmVudCB3YXlzIHRvIHZpZXcgdGliYmxlIGRhdGEKcGVuZ3VpbnMKZ2xpbXBzZShwZW5ndWlucykKVmlldyhwZW5ndWlucykKP3Blbmd1aW5zCmBgYAoKYGBge3J9CiMgcGxvdHRpbmcKZ2dwbG90KGRhdGE9cGVuZ3VpbnMsIG1hcHBpbmcgPSBhZXMoeD1mbGlwcGVyX2xlbmd0aF9tbSx5PWJvZHlfbWFzc19nKSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyhjb2xvcj1zcGVjaWVzLHNoYXBlPXNwZWNpZXMpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikrCiAgbGFicyh0aXRsZT0iQm9keSBtYXNzIGFuZCBmbGlwcGVyIGxlbmd0aCIsCiAgICAgICBzdWJ0aXRsZSA9ICJEaW1lbnNpb25zIGZvciBBZGVsaWUsIENoaW5zdHJhcCwgYW5kIEdlbnRvbyBQZW5ndWlucyIsCiAgICAgICB4ID0gIkZsaXBwZXIgbGVuZ3RoIChtbSkiLCB5PSJCb2R5IG1hc3MgKGcpIiwKICAgICAgIGNvbG9yPSJTcGVjaWVzIixzaGFwZT0iU3BlY2llcyIpKwogIHNjYWxlX2NvbG9yX2NvbG9yYmxpbmQoKQpgYGAKCiNFeGVyY2lzZSAxCmBgYHtyfQojUXVlc3Rpb24gMQpucm93KHBlbmd1aW5zKQpuY29sKHBlbmd1aW5zKQpxMT0iVGhlcmUgYXJlIDM0NCByb3dzIGFuZCA4IGNvbHVtbnMgd2l0aGluIHRoZSBwZW5ndWlucyBkYXRhc2V0IgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gMgo/cGVuZ3VpbnMKcTI9IlRoZSBiaWxsIGRlcHRoIGlzIHRoZSBsZW5ndGggZnJvbSB0aGUgdG9wIG9mIHRoZSBjdWxtZW4gYmlsbCB0byB0aGUgYm90dG9tIG9mIHRoZSBjdWxtZW4gYmlsbC4iCmBgYAoKYGBge3J9CiNRdWVzdGlvbiAzCmdncGxvdChkYXRhID0gcGVuZ3VpbnMsbWFwcGluZyA9IGFlcyh4PWJpbGxfbGVuZ3RoX21tLHk9YmlsbF9kZXB0aF9tbSkpKwogIGdlb21fcG9pbnQoKQpxMz0iVGhlcmUgYXBwZWFycyB0byBiZSB0aHJlZSBsYXJnZSBjbHVzdGVyIGdyb3VwaW5ncyBvZiBvYnNlcnZhdGlvbnMgYmV0d2VlbiBiaWxsIGRlcHRoIGFuZCBiaWxsIGxlbmd0aC4gQSBzaWduaWZpY2FudCBsaW5lYXIgdHJlbmQgYmV0d2VlbiB0aGUgb2JzZXJ2YWlvbnMgZG9lcyBub3QgYXBwZWFyIHRvIGV4aXN0LiIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDQKZ2dwbG90KGRhdGEgPSBwZW5ndWlucyxtYXBwaW5nID0gYWVzKHg9c3BlY2llcyx5PWJpbGxfZGVwdGhfbW0pKSsgZ2VvbV9ib3hwbG90KCkKcTQ9IklmIEkgdXNlIHNwZWNpZXMgd2l0aGluIGEgc2NhdHRlcnBsb3QsIHRoZSBvYmVydmF0aW9ucyB3aWxsIGJlIHNwbGl0IGludG8gdGhyZWUgbGluZXMgYXNzb2ljYXRlZCB3aXRoIGVhY2ggc3BlY2llcy4gQSBtb3JlIGFwcHJvcHJlaXRlIGdlb20gaXMgdGhlIGJveHBsb3Qgc2luY2UgaXQncyBtdWNoIGVhc2llciB0byBzZWUgdGhlIGRpc3RyaWJ0aW9ucyBvZiB0aGUgb2JlcnNhdGlvbnMuIgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gNQpxNT0iVGhlIGNvZGUgaGFzIGFuIGVycm9yIHNpbmNlIG5vIG1hcHBpbmcgYXJndW1lbnRzIGhhdmUgYmVlbiBhc3NpZ25lZC4gSW4gb3JkZXIgdG8gcmVzb2x2ZSB0aGUgaXNzdWUsIHdlIG5lZWQgdG8gYWRkaW5nIG1hcHBpbmcgYXJndW1lbnRzIHN1Y2ggYXMgYWVzKHg9YmlsbF9sZW5ndGhfbW0seT1iaWxsX2RlcHRoX21tKSIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDYKZ2dwbG90KGRhdGEgPSBwZW5ndWlucyxtYXBwaW5nID0gYWVzKHg9YmlsbF9sZW5ndGhfbW0seT1iaWxsX2RlcHRoX21tKSkrCiAgZ2VvbV9wb2ludChuYS5ybSA9IFRSVUUpCnE2PSJUaGUgbmEucm0gYXJndW1lbnQgcmVtb3ZlcyBudWxsIHZhbHVlcyBmcm9tIHRoZSBwbG90LiBCeSBkZWZhdWx0LCB0aGUgYXJndW1lbnQgaXMgc2V0IHRvIEZBTFNFLiIKCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA3CmdncGxvdChkYXRhPXBlbmd1aW5zLCBtYXBwaW5nID0gYWVzKHg9ZmxpcHBlcl9sZW5ndGhfbW0seT1ib2R5X21hc3NfZykpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3I9c3BlY2llcyxzaGFwZT1zcGVjaWVzKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpKwogIGxhYnModGl0bGU9IkJvZHkgbWFzcyBhbmQgZmxpcHBlciBsZW5ndGgiLAogICAgICAgc3VidGl0bGUgPSAiRGltZW5zaW9ucyBmb3IgQWRlbGllLCBDaGluc3RyYXAsIGFuZCBHZW50b28gUGVuZ3VpbnMiLAogICAgICAgeCA9ICJGbGlwcGVyIGxlbmd0aCAobW0pIiwgeT0iQm9keSBtYXNzIChnKSIsCiAgICAgICBjb2xvcj0iU3BlY2llcyIsc2hhcGU9IlNwZWNpZXMiLGNhcHRpb24gPSAiRGF0YSBjb21lcyBmcm9tIHRoZSBwYWxtZXJwZW5ndWlucyBwYWNrYWdlIikrCiAgc2NhbGVfY29sb3JfY29sb3JibGluZCgpCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA4CmdncGxvdChkYXRhPXBlbmd1aW5zLCBtYXBwaW5nID0gYWVzKHg9ZmxpcHBlcl9sZW5ndGhfbW0seT1ib2R5X21hc3NfZykpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoY29sb3I9YmlsbF9kZXB0aF9tbSkpICsKICBnZW9tX3Ntb290aCgpKwogIGxhYnModGl0bGU9IkJvZHkgbWFzcyBhbmQgZmxpcHBlciBsZW5ndGgiLAogICAgICAgc3VidGl0bGUgPSAiRGltZW5zaW9ucyBmb3IgQWRlbGllLCBDaGluc3RyYXAsIGFuZCBHZW50b28gUGVuZ3VpbnMiLAogICAgICAgeCA9ICJGbGlwcGVyIGxlbmd0aCAobW0pIiwgeT0iQm9keSBtYXNzIChnKSIsCiAgICAgICBjb2xvcj0iU3BlY2llcyIsc2hhcGU9IlNwZWNpZXMiLGNhcHRpb24gPSAiRGF0YSBjb21lcyBmcm9tIHRoZSBwYWxtZXJwZW5ndWlucyBwYWNrYWdlIikKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDkKZ2dwbG90KGRhdGE9cGVuZ3VpbnMsbWFwcGluZz1hZXMoeD1mbGlwcGVyX2xlbmd0aF9tbSx5PWJvZHlfbWFzc19nLGNvbG9yPWlzbGFuZCkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChzZT1GQUxTRSkKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDEwCmdncGxvdChkYXRhID0gcGVuZ3VpbnMsbWFwcGluZz1hZXMoeD1mbGlwcGVyX2xlbmd0aF9tbSx5PWJvZHlfbWFzc19nKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKHNlPUZBTFNFKQoKZ2dwbG90KCkrZ2VvbV9wb2ludChkYXRhID0gcGVuZ3VpbnMsbWFwcGluZz1hZXMoeD1mbGlwcGVyX2xlbmd0aF9tbSx5PWJvZHlfbWFzc19nKSkrZ2VvbV9zbW9vdGgoZGF0YT1wZW5ndWlucyxtYXBwaW5nPWFlcyh4PWZsaXBwZXJfbGVuZ3RoX21tLHk9Ym9keV9tYXNzX2cpKQoKcTEwPSJUaGVzZSBwbG90cyB3aWxsIGxvb2sgdmVyeSBzaW1pbGFyIGJ1dCB0aGUgZmlyc3Qgb25lIHdpbGwgbm90IGhhdmUgYSBjb25maWRlbmNlIHJhbmdlIGRpc3BsYXllZC4iCmBgYAoKYGBge3J9CiNSZW1vdmUgZGF0YSBhbmQgbWFwcGluZyB0ZXh0CmdncGxvdChwZW5ndWlucyxhZXMoeD1mbGlwcGVyX2xlbmd0aF9tbSx5PWJvZHlfbWFzc19nKSkrZ2VvbV9wb2ludCgpCmBgYAoKYGBge3J9CiNQaXBpbmcKcGVuZ3VpbnMgfD4KICBnZ3Bsb3QoYWVzKHg9ZmxpcHBlcl9sZW5ndGhfbW0seT1ib2R5X21hc3NfZykpICsKICBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KI0NhdGVnb3JpY2FsIFZhcmlhYmxlcwpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9c3BlY2llcykpK2dlb21fYmFyKCkKYGBgCgpgYGB7cn0KI09yZGVyaW5nIGZhY3RvcgpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9ZmN0X2luZnJlcShzcGVjaWVzKSkpK2dlb21fYmFyKCkKYGBgCgpgYGB7cn0KI0hpc3RvZ3JhbQpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9Ym9keV9tYXNzX2cpKStnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIwMCkKYGBgCgpgYGB7cn0KZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWJvZHlfbWFzc19nKSkrZ2VvbV9kZW5zaXR5KCkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxMQpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHk9c3BlY2llcykpK2dlb21fYmFyKCkKcTExPSJUaGUgcGVuZ3VpbiBjYXRlZ29yaWVzIGFyZSByb3RhdGVkIGhvcml6b250YWxseSB3aGVuIHVzaW5nIHRoZSB5IGFlc3RoZXRpYy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTIKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PXNwZWNpZXMpKStnZW9tX2JhcihmaWxsPSJyZWQiKQpxMTI9IlRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBwbG90cyBpcyB0aGF0IHRoZSBmaWxsIGFyZ3VtZW50IGNoYW5nZXMgdGhlIGJhciBncmFwaCBjb2xvciB3aGlsZSB0aGUgY29sb3IgY2hhbmdlcyB0aGUgYmFyIGdyYXBoIGJvcmRlciBjb2xvci4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTMKcTEzPSJUaGUgYmlucyBhcmd1bWVudCBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgYnVja2V0cyB0aGUgaGlzdG9ncmFtIHdpbGwgdXNlLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxNApoZWFkKGRpYW1vbmRzKQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9Y2FyYXQpKStnZW9tX2hpc3RvZ3JhbShiaW5zID0gMTUpCnExND0iSSBiZWxpZXZlIHRoZSBiaW4gc2l6ZSB3aXRoIDE1IGdyb3VwaW5ncyBpcyB0aGUgbW9zdCBpbnRlcmVzdGluZyBzaW5jZSB3ZSdyZSBhYmxlIHRvIGNsZWFybHkgc2VlIHRoZSBkaXN0cmlidXRpb24uIgpgYGAKCmBgYHtyfQojQm94cGxvdApnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9c3BlY2llcyx5PWJvZHlfbWFzc19nKSkrZ2VvbV9ib3hwbG90KCkKCiNEZW5zaXR5IFBsb3QKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWJvZHlfbWFzc19nLGNvbG9yPXNwZWNpZXMsZmlsbD1zcGVjaWVzKSkrZ2VvbV9kZW5zaXR5KGFscGhhPS41KQpgYGAKCmBgYHtyfQojQ2F0ZWdvcnkgdnMgQ2F0ZWdvcnkKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWlzbGFuZCxmaWxsPXNwZWNpZXMpKStnZW9tX2JhcigpCgpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9aXNsYW5kLGZpbGw9c3BlY2llcykpK2dlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKQpgYGAKCmBgYHtyfQojVGhyZWUgb3IgTW9yZSBWYXJpYWJsZXMKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWZsaXBwZXJfbGVuZ3RoX21tLHk9Ym9keV9tYXNzX2cpKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1zcGVjaWVzLHNoYXBlPWlzbGFuZCkpKwogIGZhY2V0X3dyYXAofmlzbGFuZCkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxNQpoZWFkKG1wZykKcTE1PSJtYW51ZmFjdHVyZXI9Y2F0ZWdvcmljYWwsIG1vZGVsPWNhdGVnb3JpY2FsLCBkaXNwbD1udW1lcmljYWwseWVhcj1jYXRlZ29yaWNhbCxjeWw9Y2F0ZWdvcmljYWwsdHJhbnM9Y2F0ZWdvcmljYWwsZHJ2PWNhdGVnb3JpY2FsLCBjdHk9bnVtZXJpY2FsLCBod3k9bnVtZXJpY2FsLi4uIEkgYW0gYWJsZSB0byBkZXRlcm1pbmUgdGhlc2UgY2F0ZWdvcmllcyBieSBsb29raW5nIGF0IHRoZSBudW1iZXIgb2Ygb2NjdXJhbmNpZXMgYW5kIGJhY2tncm91bmQgaW5mb3JtYXRpb24uIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDE2CmdncGxvdChtcGcsYWVzKHg9aHd5LHk9ZGlzcGwsc2l6ZT1jdHksY29sb3I9Y3R5LGxpbmV3aWR0aD1jdHkpKStnZW9tX3BvaW50KCkKcTE2PSJGb3IgbnVtZXJpY2FsIHZhbHVlcyBhIHNjYWxlIGlzIGludHJvZHVjZWQgYW5kIGZvciBjYXRlZ29yaWNhbCB2YWx1ZXMgYSBuZXcgY29sb3IgaXMgdXNlZCBmb3IgZWFjaCBncm91cGluZy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTcKcTE3PSJUaGVyZSBpcyBubyBjaGFuZ2Ugc2luY2UgbGluZSB3aWR0aCBkb2VzIG5vdCBhZmZlY3QgYSBzY2F0dGVyIHBsb3QiCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTgKcTE4PSJBIHZhcmlhYmxlIGNhbiBiZSB1c2VkIGluIHNldmVyYWwgYXNldGhldGljcyB3aXRoaW4gdmlzdWFsaXphdGlvbi4gSWYgdGhpcyBvY2N1cnMsIGVhY2ggYXNldGhldGljcyB3aWxsIGJlIGFmZmVzdGVkIGFjY29yZGluZ2x5LiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxOQpnZ3Bsb3QoZGF0YT1wZW5ndWlucyxtYXBwaW5nID0gYWVzKHg9YmlsbF9sZW5ndGhfbW0seT1iaWxsX2RlcHRoX21tLGNvbG9yPXNwZWNpZXMsc2hhcGU9c3BlY2llcykpK2dlb21fcG9pbnQoKQpxMTk9IkluIG9yZGVyIHRvIGZpeCB0aGlzIHByb2JsZW0sIHRoZSBhcmd1bWVudHMgd2l0aGluIHRoZSBnZW9tX3BvaW50IGZ1bmN0aW9uIG5lZWQgdG8gYmUgcmVtb3ZlZC4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMjAKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWlzbGFuZCxmaWxsPXNwZWNpZXMpKSsKICBnZW9tX2Jhcihwb3NpdGlvbj0iZmlsbCIpCmdncGxvdChwZW5ndWlucyxhZXMoeD1zcGVjaWVzLGZpbGw9aXNsYW5kKSkrCiAgZ2VvbV9iYXIocG9zaXRpb249ImZpbGwiKQpxMjA9InBsb3QgMSBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHNwZWNpZXMgb24gZWFjaCBpc2xhbmQgd2hpbGUgcGxvdCAyIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgZWFjaCBzcGVjaWVzIHdpdGggZWFjaCBvZiB0aGUgaXNsYW5kcy4iCmBgYAoKYGBge3J9CiNnZ3NhdmUKZ2dwbG90KHBlbmd1aW5zLGFlcyh4PWZsaXBwZXJfbGVuZ3RoX21tLHk9Ym9keV9tYXNzX2cpKStnZW9tX3BvaW50KCkKZ2dzYXZlKGZpbGVuYW1lPSJwZW5ndWluLXBsb3QucG5nIikKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAyMQpnZ3Bsb3QobXBnLGFlcyh4PWNsYXNzKSkrCiAgZ2VvbV9iYXIoKQpnZ3Bsb3QobXBnLGFlcyh4PWN0eSx5PWh3eSkpKwogIGdlb21fcG9pbnQoKQpnZ3NhdmUoIm1wZy1wbG90LnBkZiIpCgpxMjE9IlRoZSBzZWNvbmQgcGxvdCBpcyBzYXZlZCBzaW5jZSB0aGUgZ2dzYXZlIGZ1bmN0aW9uIHdhcyBydW4gYWZ0ZXIgdGhlIHNlY29uZCBzZXQgb2YgcGxvdHRpbmcgY29kZS4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMjIKcTIyPSJUbyBzYXZlIHRoZSBwbG90IGFzIGEgcGRmLCB0aGUgZmlsZSBleHRlbnNpb24gd291bGQgbmVlZCB0byBiZSB1cGRhdGVkIHRvIC5wZGYgaW5zdGVhZCBvZiAucG5nIgpgYGAKCiMgQ2hhcHRlciAyOiBXb3JrZmxvdyBCYXNpY3MKYGBge3J9CiNWZWN0b3IKcHJpbWVzIDwtIGMoMiwzLDUsNywxMSwxMykKcHJpbWVzKjIKdGhpc19pc19hX3JlYWxseV9sb25nX25hbWU8LTIuNQpgYGAKCmBgYHtyfQpzZXEoMSwxMCkKeDwtImhlbGxvIHdvcmxkIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDIzCnEyMzwtIlRoZSBjb2RlIGRvZXMgbm90IHdvcmsgYmVjYXVzZSB0aGUgdmFyaWFibGUgaXMgbWlzc3BlbGxlZCIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAyNAojIGxpYnJhcnkodGlkeXZlcnNlKQojIGdncGxvdChkVEEsYWVzKHg9ZGlzcGwseT1od3kpKSsKIyAgIGdlb21fcG9pbnQoKSsKIyAgIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iKQpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDI1CnEyNTwtIm9wdGlvbiBzaGlmdCBrIGRpc3BsYXlzIFJTdHVkaW8gc2hvcnRjdXRzLiBUaGlzIGNhbiBhbHNvIGJlIHZpZXdlZCBmcm9tIHRoZSBoZWxwIG1lbnUuIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDI2CnEyNjwtIlRoZSBzZWNvbmQgcGxvdCBpcyBzYXZlZCB0aGlzIHRpbWUgc2luY2UgdGhlIHBsb3QgYXJndW1lbnQgc3BlY2lmaWVzIHRoZSBmaXJzdCBncmFwaC4iCmBgYAoKIyBDaGFwdGVyIDM6IERhdGEgVHJhbnNmb3JtYXRpb24KYGBge3J9CmxpYnJhcnkobnljZmxpZ2h0czEzKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpgYGB7cn0KZmxpZ2h0cwoKI1VzZSB2aWV3IHRvIHNlZSBhbiBlbnRpZXIgdGliYmxlClZpZXcoZmxpZ2h0cykKCiNVc2UgdG8gc2VlIGFsbCBjb2x1bW5zCmdsaW1wc2UoZmxpZ2h0cykKYGBgCgpgYGB7cn0KI0ZpbHRlcgpmbGlnaHRzIHw+CiAgZmlsdGVyKGRlc3Q9PSJJQUgiKSB8PgogIGdyb3VwX2J5KHllYXIsbW9udGgsZGF5KSB8PgogIHN1bW1hcmlzZSgKICAgIGFycl9kZWxheSA9IG1lYW4oYXJyX2RlbGF5LG5hLnJtID0gVFJVRSkKICApCgpmbGlnaHRzIHw+CiAgZmlsdGVyKGRlcF9kZWxheT4xMjApCgpqYW4xPC1mbGlnaHRzIHw+CiAgZmlsdGVyKG1vbnRoID09MSAmIGRheT09MSkKCmZsaWdodHMgfD4KICBmaWx0ZXIobW9udGggPT0xIHwgbW9udGg9PTIpCgpmbGlnaHRzIHw+CiAgZmlsdGVyKG1vbnRoICVpbiUgYygxLDIpKQoKZmxpZ2h0cyB8PgogIGZpbHRlcihtb250aD09MSkKCmBgYAoKYGBge3J9CiNBcnJhbmdlCmZsaWdodHMgfD4KICBhcnJhbmdlKHllYXIsbW9udGgsZGF5LGRlc2MoZGVwX3RpbWUpKQpgYGAKCmBgYHtyfQojRGlzdGluY3QKZmxpZ2h0cyB8PgogIGRpc3RpbmN0KG9yaWdpbixkZXN0LC5rZWVwX2FsbCA9IFRSVUUpCmBgYAoKYGBge3J9CmZsaWdodHMgfD4KICBjb3VudChvcmlnaW4sZGVzdCxzb3J0PVRSVUUpCgp0YWJsZShmbGlnaHRzJGNhcnJpZXIpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMjcKZmxpZ2h0cyB8PgogIGZpbHRlcihhcnJfZGVsYXk+PTEyMCkKCmZsaWdodHMgfD4KICBmaWx0ZXIoZGVzdCAlaW4lIGMoJ0lBSCcsJ0hPVScpKQoKZmxpZ2h0cyB8PgogIGZpbHRlcihjYXJyaWVyICVpbiUgYygnVUEnLCdETCcpKQoKZmxpZ2h0cyB8PgogIGZpbHRlcihtb250aCAlaW4lIGMoNyw4LDkpKQoKZmxpZ2h0cyB8PgogIGZpbHRlcihkZXBfZGVsYXk8PTAgJiBhcnJfZGVsYXk+PTEyMCkKCmZsaWdodHMgfD4KICBmaWx0ZXIoZGVwX2RlbGF5Pj02MCAmIGFycl9kZWxheSA8PTMwKQoKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAyOApmbGlnaHRzIHw+CiAgYXJyYW5nZShkZXNjKGRlcF9kZWxheSkpCgpmbGlnaHRzIHw+CiAgYXJyYW5nZShkZXNjKGRlcF9kZWxheSkpCgpmbGlnaHRzIHw+CiAgYXJyYW5nZShkZXBfdGltZSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAyOQpmbGlnaHRzIHw+CiAgYXJyYW5nZShhaXJfdGltZSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAzMCAKcTMwPC0iWWVzIgpmbGlnaHRzIHw+CiAgZGlzdGluY3QobW9udGgsZGF5LC5rZWVwX2FsbCA9IFRSVUUpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMzEKZmxpZ2h0cyB8PgogIGFycmFuZ2UoZGVzYyhkaXN0YW5jZSkpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMzIKcTMyPC0iSXQncyBpbXBvcnRhbnQgdG8gZmlsdGVyIHRoZSBkYXRhIGZpcnN0IGFuZCB0aGVuIHBlcmZvcm0gYW55IGFycmFuZ2VtZW50cy4gUmVtb3ZpbmcgdW5uZWVkZWQgZGF0YSB3aWxsIGFsbG93IHRoZSBhcnJhbmdlIGZ1bmN0aW9uIHRvIGNvbXBsZXRlIG11c3QgZmFzdGVyIHNpbmNlIHRoZXJlIGlzIGxlc3MgZGF0YSB0byBldmFsdWF0ZS4iCmBgYAoKYGBge3J9CiMgTXV0YXRlCmZsaWdodHMgfD4KICBtdXRhdGUoCiAgICBnYWluID0gZGVwX2RlbGF5IC0gYXJyX2RlbGF5LAogICAgc3BlZWQgPSBkaXN0YW5jZSAvIGFpcl90aW1lICogNjAsCiAgICAuYmVmb3JlID0gMgogICkKYGBgCgpgYGB7cn0KIyBNdXRhdGUKZmxpZ2h0cyB8PgogIG11dGF0ZSgKICAgIGdhaW4gPSBkZXBfZGVsYXkgLSBhcnJfZGVsYXksCiAgICBzcGVlZCA9IGRpc3RhbmNlIC8gYWlyX3RpbWUgKiA2MCwKICAgIC5hZnRlciA9IGRheQogICkKYGBgCgpgYGB7cn0KIyBNdXRhdGUKZmxpZ2h0cyB8PgogIG11dGF0ZSgKICAgIGdhaW4gPSBkZXBfZGVsYXkgLSBhcnJfZGVsYXksCiAgICBob3VycyA9IGFpcl90aW1lIC8gNjAsCiAgICBnYWluX3Blcl9ob3VyID0gZ2FpbiAvIGhvdXJzLAogICAgLmtlZXAgPSAidXNlZCIKICApCmBgYAoKYGBge3J9CiMgU2VsZWN0LCByZW5hbWUsIHJlbG9jYXRlCmZsaWdodHMgfD4KICBzZWxlY3QoeWVhcixtb250aCxkYXkpCgpmbGlnaHRzIHw+CiAgc2VsZWN0KHllYXI6ZGF5KQoKZmxpZ2h0cyB8PgogIHNlbGVjdCgheWVhcjpkYXkpCgpmbGlnaHRzIHw+CiAgc2VsZWN0KHdoZXJlKGlzLmNoYXJhY3RlcikpCgpmbGlnaHRzIHw+CiAgc2VsZWN0KHRhaWxfbnVtID0gdGFpbG51bSkKCmZsaWdodHMgfD4KICByZW5hbWUodGFpbF9udW0gPSB0YWlsbnVtKQoKZmxpZ2h0cyB8PgogIHJlbG9jYXRlKHRpbWVfaG91cixhaXJfdGltZSkKCmZsaWdodHMgfD4KICByZWxvY2F0ZSh5ZWFyOmRlcF90aW1lLC5hZnRlcj10aW1lX2hvdXIpCgpmbGlnaHRzIHw+CiAgcmVsb2NhdGUoc3RhcnRzX3dpdGgoImFyciIpLC5iZWZvcmU9ZGVwX3RpbWUpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMzMKcTMzPC0iSSB3b3VsZCBleHBlY3QgdGhlc2UgdmFyaWFibGVzIHRvIGFsbCBiZSByZWxhdGVkIHRvIGEgcGxhbmUncyBkZXBhdHVyZS4gRGVwYXJ0dXJlIGRlbGF5IHdvdWxkIHJlcHJlc2VudCB0aGUgdGltZSBiZXR3ZWVuIHNjaGVkX2RlcF90aW1lIGFuZCBEZXBfdGltZS4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMzQKcTM0PC0iVGhlcmUgYXJlIGEgbG90IG9mIG1ldGhvZHMgYnV0IEkgd291bGQgdXNlIHRoZSBzZWxlY3QgZnVuY3Rpb24gYW5kIGRlZmluZSBlYWNoIGNvbHVtbiBvciBJIHdvdWxkIHVzZSB0aGUgc2VsZWN0IGZ1bmN0aW9uIGFuZCB0aGUgY29udGFpbnMgZnVuY3Rpb24gdG8gZmluZCBEZWxheSIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAzNQpmbGlnaHRzIHw+CiAgc2VsZWN0KHRhaWxudW0sdGFpbG51bSkKCnEzNTwtIklmIHRoZSBzYW1lIGNvbHVtbiBpcyBsaXN0ZWQgdHdpY2UsIHRoZSBjb2x1bW4gd2lsbCBvbmx5IGJlIHB1bGxlZCBpbiBvbmNlLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAzNgpxMzY8LSJUaGUgYW55X29mKCkgZnVuY3Rpb24gaGVscHMgd2l0aCBzZWxlY3RpbmcgZGF0YSB0aGF0IG1lZXRzIGEgcGFydGljdWxhciBmaWx0ZXIgY3JpdGVyYS4gU3BlY2lmaWNhbGx5LCB0aGUgZnVuY3Rpb25zIG1lYW5zIHNlbGVjdCBhbnkgZGF0YSBmcm9tIHRoZSBzcGVjaWZpZWQgY29sdW1ucyB0aGF0IG1lZXQgYSBjb25kaXRpb24uIEZvciB0aGlzIGV4YW1wbGUsIGl0IHdvdWxkIGJlIGhlbHAgYmVjYXVzZSB3ZSB3b3VsZCBiZSBhYmxlIHRvIHNlbGVjdCBwYXJ0aWN1bGFyIGZsaWdodHMgYmFzZWQgdXBvbiBhIHNwZWNpZmllZCBjb25kaXRpb24uIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDM3CmZsaWdodHMgfD4gc2VsZWN0KGNvbnRhaW5zKCJUSU1FIikpCnEzNzwtIlRoaXMgZnVuY3Rpb24gc2VsZWN0cyBhbnkgY29sdW1ucyB0aGF0IGNvbnRhaW5zIHRoZSB3b3JkIHRpbWUgcmVnYXJkbGVzcyBvZiBjYXNlLiBJZiBjYXNlIGlzIGltcG9ydGFudCwgd2UgY291bGQgYWRkIHRoZSBpZ25vcmUuY2FzZSBhcmd1bWVudC4iCmBgYAoKYGBge3J9CiNRdWVzdGlvbiAzOApmbGlnaHRzIHw+CiAgc2VsZWN0KGFpcl90aW1lX21pbj1haXJfdGltZSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAzOQpxMzk8LSJUaGUgY29kZSByZXN1bHRzIGluIGFuIGVycm9yIHNpbmNlIGFycl9kZWxheSB3YXMgbm90IHNlbGVjdGVkIHdpdGhpbiB0aGUgc2VsZWN0IGZ1bmN0aW9uLiIKYGBgCgpgYGB7cn0KI0V4YW1wbGUKZmxpZ2h0cyB8PgogIGZpbHRlcihkZXN0PT0iSUFIIikgfD4KICBtdXRhdGUoc3BlZWQgPSBkaXN0YW5jZSAvIGFpcl90aW1lICogNjApIHw+CiAgYXJyYW5nZShkZXNjKHNwZWVkKSkKYGBgCgpgYGB7cn0KI0dyb3VwIEJ5CmZsaWdodHMgfD4KICBncm91cF9ieShtb250aCkKCmZsaWdodHMgfD4gCiAgZ3JvdXBfYnkobW9udGgpIHw+IAogIHN1bW1hcmlzZSgKICAgIGF2Z19kZWxheSA9IG1lYW4oZGVwX2RlbGF5LG5hLnJtID0gVFJVRSksCiAgICBuPW4oKQogICkKYGBgCgpgYGB7cn0KZmxpZ2h0cyB8PiAKICBncm91cF9ieShkZXN0KSB8PiAKICBzbGljZV9tYXgoYXJyX2RlbGF5LG49MSx3aXRoX3RpZXMgPSBGQUxTRSkgfD4gCiAgcmVsb2NhdGUoZGVzdCkKYGBgCgpgYGB7cn0KZGFpbHk8LWZsaWdodHMgfD4gCiAgZ3JvdXBfYnkoeWVhcixtb250aCxkYXkpCmBgYAoKYGBge3J9CmRhaWx5IHw+CiAgc3VtbWFyaXNlKAogICAgbj1uKCksCiAgICAuZ3JvdXBzPSJkcm9wX2xhc3QiCiAgKQoKZGFpbHkgfD4KICBzdW1tYXJpc2UoCiAgICBuPW4oKSwKICAgIC5ncm91cHM9ImRyb3AiCiAgKQoKZGFpbHkgfD4gCiAgdW5ncm91cCgpCgpkYWlseSB8PgogIHVuZ3JvdXAoKSB8PiAKICBzdW1tYXJpc2UoCiAgICBhdmdfZGVsYXkgPSBtZWFuKGRlcF9kZWxheSxuYS5ybT1UUlVFKSwKICAgIGZsaWdodHM9bigpCiAgKQoKZmxpZ2h0cyB8PgogIHN1bW1hcmlzZSgKICAgIGRlbGF5ID0gbWVhbihkZXBfZGVsYXksbmEucm09VFJVRSksCiAgICBuPW4oKSwKICAgIC5ieT1jKG9yaWdpbixkZXN0KQogICkKYGBgCgpgYGB7cn0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpCiMgUXVlc3Rpb24gNDAKZmxpZ2h0cyB8PiAKICBncm91cF9ieShjYXJyaWVyLGRlc3QpIHw+IAogIHN1bW1hcmlzZShkZWxheSA9IHN1bShkZXBfZGVsYXksbmEucm09VFJVRSksbj1uKCkpIHw+IAogIG11dGF0ZShhdmdfZGVsYXk9ZGVsYXkvbikgfD4KICBhcnJhbmdlKGRlc2MoYXZnX2RlbGF5KSkKCmZsaWdodHMgfD4gCiAgZ3JvdXBfYnkoY2FycmllcikgfD4KICBzdW1tYXJpc2UoZGVsYXk9bWVhbihkZXBfZGVsYXkrYXJyX2RlbGF5LG5hLnJtID0gVFJVRSkpIHw+IAogIGFycmFuZ2UoZGVzYyhkZWxheSkpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gNDEKZmxpZ2h0cyB8PiAKICBncm91cF9ieShkZXN0KSB8PiAKICBzbGljZV9tYXgoYXJyX2RlbGF5LG49MSx3aXRoX3RpZXMgPSBUUlVFKSB8PiAKICBhcnJhbmdlKGRlc2MoZGVwX2RlbGF5KSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA0MgpmbGlnaHRzIHw+IAogIGdyb3VwX2J5KGRlcF90aW1lKSB8PiAKICBzdW1tYXJpc2UobWVhbl9kZWxheT1tZWFuKGFycl9kZWxheSxuYS5ybSA9IFRSVUUpKSB8PiAKICBnZ3Bsb3QoYWVzKHg9ZGVwX3RpbWUseT1tZWFuX2RlbGF5KSkrCiAgZ2VvbV9saW5lKCkKCnE0MjwtIlRoZSBkZWxheXMgYXBwZWFycyB0byBkZWNyZWFzZSBzaWduaWZpY2FudGx5IGFmdGVyIHRoZSBtb3JuaW5nLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA0MwpxNDM8LSJJZiBhIG5lZ2F0aXZlIHZhbHVlIGlzIGludHJvZHVjZWQsIGFsbCByb3dzIHdpdGhpbiB0aGUgdGliYmxlIHdpbGwgYmUgZGlzcGxheWVkLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA0NApxNDQ8LSJUaGUgY291bnQgZnVuY3Rpb24gZGlzcGxheXMgdGhlIG51bWJlciBvZiB1bmlxdWUgdmFsdWVzLiBUaGUgY291bnQgdmFsdWVzIGNhbiB0aGVuIGJ5IHNvcnRlZCBieSB0aGUgYXJyYW5nZSBmdW5jdGlvbi4gSW4gYWRkaXRpb24sIHRoZSBzb3J0IGF0dHJpYnV0ZSBjYW4gYmUgdXNlZCB0byBhcnJhbmdlIHRoZSBjb3VudCB2YWx1ZXMuIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDQ1CmRmIDwtIHRpYmJsZSgKICB4PTE6NSwKICB5PWMoImEiLCJiIiwiYSIsImEiLCJiIiksCiAgej1jKCJLIiwiSyIsIkwiLCJMIiwiSyIpCikKCiBkZiB8PiAKICAgZ3JvdXBfYnkoeSkKIAogcTQ1PC0iVGhlcmUgaXMgdmlzdWFsbHkgbm8gY2hhbmdlcyBidXQgdGhlIHRpYmJsZSBpcyBub3cgZ3JvdXBlZCBieSB0aGUgeSB2YXJpYWJsZS4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gNDYKZGYgfD4KICBhcnJhbmdlKHkpCnE0NjwtIlRoZSB0aWJibGUgaXMgc29ydGVkIGFscGhhYmV0aWNhbGx5IG9uIHRoZSB5IHZhcmlhYmxlIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDQ3CmRmIHw+IAogIGdyb3VwX2J5KHkpIHw+IAogIHN1bW1hcmlzZShtZWFuX3g9bWVhbih4KSkKcTQ3PC0iVGhlIHRpYmJsZSBpcyBncm91cGVkIGJ5IHZhcmlhYmxlIHkgYW5kIGlzIHRoZW4gYSBtZWFuIHN1bW1hcml6ZSBmdW5jdGlvbiBpcyBjYWxsZWQuIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDQ4CmRmIHw+IAogIGdyb3VwX2J5KHkseikgfD4gCiAgc3VtbWFyaXNlKG1lYW5feD1tZWFuKHgpLC5ncm91cHMgPSAiZHJvcCIpCnE0ODwtIlRoZSB1bmlxdWUgeSBhbmQgeiB2YXJpYWJsZSBjb21iaW5hdGlvbnMgYXJlIHN1bW1hcml6ZWQgYnkgdGFraW5nIHRoZSBtZWFuIG1lYW4gb2YgeC4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gNDkKZGYgfD4gCiAgZ3JvdXBfYnkoeSx6KSB8PiAKICBzdW1tYXJpc2UobWVhbl94PW1lYW4oeCkpCgpkZiB8PiAKICBncm91cF9ieSh5LHopIHw+IAogIG11dGF0ZShtZWFuX3ggPSBtZWFuKHgpKQoKcTQ5PC0iVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGVzZSB0d28gcGlwZWxpbmVzIGlzIHRoYXQgdGhlIGZpcnN0IG9uZSBzdW1tYXJpemVzIHdpdGggdGhlIG1lYW4gZnVuY3Rpb24gYW5kIHRoZSBzZWNvbmQgb25lIGFkZHMgYSBuZXcgY29sdW1uIGJhc2VkIHVwb24gdGhlIG1lYW4gb2YgeC4iCmBgYAoKIyBDaGFwdGVyIDQ6IFdvcmtmbG93IENvZGUgU3R5bGUKYGBge3J9CmxpYnJhcnkoc3R5bGVyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShueWNmbGlnaHRzMTMpCiNDb21tYW5kICsgU2hpZnQgKyBQCmBgYAoKYGBge3J9CiNzdGl2ZSBmb3IKI3ogPC0gKGEgKyBiKV4yIC8gZAoKI2F2b2lkCiN6PC0oIGEgKyBiICkgXiAyL2QKCiNjbWQgKyBzaGlmdCArIFIgCgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDUwCmZsaWdodHMgfD4KICBmaWx0ZXIoZGVzdD09IklBSCIpIHw+CiAgZ3JvdXBfYnkoeWVhcixtb250aCxkYXkpIHw+IAogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgZGVsYXk9bWVhbihhcnJfZGVsYXksCiAgICBuYS5ybT1UUlVFKSkgfD4gCiAgZmlsdGVyKG4+MTApIAoKZmxpZ2h0cyB8PiAKICBmaWx0ZXIoCiAgICBjYXJyaWVyPT0iVUEiLAogICAgZGVzdCVpbiVjKCJJQUgiLCJIT1UiKSwKICAgIHNjaGVkX2RlcF90aW1lPjA5MDAsCiAgICBzY2hlZF9hcnJfdGltZTwyMDAwKSB8PiAKICBncm91cF9ieShmbGlnaHQpIHw+IAogIHN1bW1hcmlzZShkZWxheT1tZWFuKGFycl9kZWxheSxuYS5ybSA9IFRSVUUpLGNhbmNlbGxlZD1zdW0oaXMubmEoYXJyX2RlbGF5KSksbj1uKCkpIHw+IAogIGZpbHRlcihuPjEwKQpgYGAKCiMgQ2hhcHRlciA0OiBXb3JrZmxvdyBDb2RlIFN0eWxlCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDUxCiNUYWJsZSAxCnE1MT1jKHQxLHQyLHQzKQoKdDE8LSJBIHNpbmdsZSByb3cgcmVwcmVzZW50cyB0aGUgbnVtYmVyIG9mIFRCIGNhc2VzIGluIGEgc3BlY2lmaWMgY291bnRyeSBmb3IgYSBzaW5nbGUgeWVhci4gVGhlIGNvbHVtbiB2YXJpYWJsZXMgYXJlIHNlbGYgZXhwbGFpbmF0b3J5LiBZZWFyPVllYXIsIENvdW50cnkgPSBDb3VudHJ5LCBudW1iZXIgPSBudW1iZXIgb2YgY2FzZXMsIHBvcHVsYXRpb24gPSBwb3B1bGF0aW9uLiIKCnQyPC0iQSBzaW5nbGUgcm93IHJlcHJlc2VudHMgdGhlIG51bWJlciBvZiBUQiBjYXNlcyBpbiBhIHNwZWNpZmljIGNvdW50cnkgZm9yIGEgc2luZ2xlIHllYXIuIFRoZSBkaWZmZXJlbmNlIGlzIHRoYXQgdGhpcyB0YWJsZSBpcyBncm91cGVkIGJ5IG1ldHJpYyBjb3VudC4iCgp0MzwtIkEgc2luZ2xlIHJvdyByZXByZXNlbnRzIHRoZSByYXRlIG9mIFRCIGNhc2VzIGluIGEgc3BlY2lmaWMgY291bnRyeSBmb3IgYSBzaW5nbGUgeWVhci4gVGhlIGRpZmZlcmVuY2UgaXMgdGhhdCB0aGlzIHRhYmxlIG9ubHkgaGFzIGNvdW50cnksIHllYXIgYW5kIHJhdGUuIgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gNTIKcTUyPC0iSW4gb3JkZXIgdG8gcHJvcGVybHkgZ2V0IHRoZSBtdXRhdGlvbiByZXN1bHRzIEkgd291bGQgaGF2ZSB0byBzcGxpdCB0aGUgdGFibGVzIGFwYXJ0IC8gdXNlIGEgcmVndWxhciByZWdyZXNzaW9uIGFuZCB0aGVuIGpvaW4gdGhlIHRhYmxlcyBiYWNrIHRvIGVhY2ggb3RoZXIgYnkgY291bnRyeS4iCmBgYAoKYGBge3J9CiNwaXZvdF9sb25nZXIoKSAvIHBpdm90X3dpZGVyKCkKYmlsbGJvYXJkCgpiaWxsYm9hcmQgfD4gCiAgcGl2b3RfbG9uZ2VyKAogICAgY29sPXN0YXJ0c193aXRoKCJ3ayIpLAogICAgbmFtZXNfdG8gPSAid2VlayIsCiAgICB2YWx1ZXNfdG8gPSAicmFuayIsCiAgICB2YWx1ZXNfZHJvcF9uYSA9IFRSVUUKICApIHw+IAogIG11dGF0ZSgKICAgIHdlZWsgPSBwYXJzZV9udW1iZXIod2VlaykKICApCmBgYAoKYGBge3J9CmJpbGxib2FyZCB8PiAKICBwaXZvdF9sb25nZXIoCiAgICBjb2w9c3RhcnRzX3dpdGgoIndrIiksCiAgICBuYW1lc190byA9ICJ3ZWVrIiwKICAgIHZhbHVlc190byA9ICJyYW5rIiwKICAgIHZhbHVlc19kcm9wX25hID0gVFJVRQogICkgfD4gCiAgbXV0YXRlKAogICAgd2VlayA9IHBhcnNlX251bWJlcih3ZWVrKQogICkgfD4gCiAgZ2dwbG90KGFlcyh4PXdlZWsseT1yYW5rLGdyb3VwPXRyYWNrKSkrCiAgZ2VvbV9saW5lKGFscGhhPTAuMjUpKwogIHNjYWxlX3lfcmV2ZXJzZSgpCmBgYApgYGB7cn0KZGYgPC0gdHJpYmJsZSgKICB+aWQsIH5icDEsIH5icDIsCiAgIkEiLCAxMDAsIDEyMCwKICAiQiIsIDE0MCwgMTE1LAogICJDIiwgMTIwLCAxMjUKKQpgYGAKCmBgYHtyfQpkZiB8PiAKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gYnAxOmJwMiwKICAgIG5hbWVzX3RvID0gIm1lYXN1cmVtZW50IiwKICAgIHZhbHVlc190byA9ICJ2YWx1ZSIKICApCmBgYAoKYGBge3J9CndobzIgfD4gCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9ICEoY291bnRyeTp5ZWFyKSwKICAgIG5hbWVzX3RvID0gYygiZGlhZ25vc2lzIiwiZ2VuZGVyIiwiYWdlIiksCiAgICBuYW1lc19zZXAgPSAiXyIsCiAgICB2YWx1ZXNfdG8gPSAiY291bnQiCiAgKQpgYGAKCmBgYHtyfQpob3VzZWhvbGQgfD4gCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9ICFmYW1pbHksCiAgICBuYW1lc190byA9IGMoIi52YWx1ZSIsImNoaWxkIiksCiAgICBuYW1lc19zZXAgPSAiXyIsCiAgICB2YWx1ZXNfZHJvcF9uYSA9IFRSVUUKICApCmBgYAoKYGBge3J9CiNQaXZvdCBXaWRlcgpjbXNfcGF0aWVudF9leHBlcmllbmNlCgpjbXNfcGF0aWVudF9leHBlcmllbmNlIHw+IAogIGRpc3RpbmN0KG1lYXN1cmVfY2QsbWVhc3VyZV90aXRsZSkKCmNtc19wYXRpZW50X2V4cGVyaWVuY2UgfD4gCiAgcGl2b3Rfd2lkZXIoCiAgICBpZF9jb2xzPXN0YXJ0c193aXRoKCJvcmciKSwKICAgIG5hbWVzX2Zyb20gPSBtZWFzdXJlX2NkLAogICAgdmFsdWVzX2Zyb20gPSBwcmZfcmF0ZQogICkKCmBgYAoKYGBge3J9CmRmIDwtIHRyaWJibGUoCiAgfmlkLH5tZWFzdXJlbWVudCx+dmFsdWUsCiAgIkEiLCAiYnAxIiwgMTAwLAogICJCIiwgImJwMSIsIDE0MCwKICAiQiIsICJicDIiLCAxMTUsCiAgIkEiLCAiYnAyIiwgMTIwLAogICJBIiwgImJwMyIsIDEwNQopCgpkZiB8PiAKICBwaXZvdF93aWRlcigKICAgIG5hbWVzX2Zyb20gPSBtZWFzdXJlbWVudCwKICAgIHZhbHVlc19mcm9tID0gdmFsdWUKICApCgpkZiB8PiAKICBkaXN0aW5jdChtZWFzdXJlbWVudCkgfD4gCiAgcHVsbCgpCgpkZiB8PiAKICBzZWxlY3QoLW1lYXN1cmVtZW50LC12YWx1ZSkgfD4gCiAgZGlzdGluY3QoKQoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKYGBgCiMgQ2hhcHRlciA2OiBXb3JrZmxvdzogU2NyaXB0cyBhbmQgUHJvamVjdHMKYGBge3J9CnVzZXRoaXM6OnVzZV9ibGFua19zbGF0ZSgpCmBgYAoKYGBge3J9CmdldHdkKCkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjYXJldCkKCmdncGxvdChkaWFtb25kcyxhZXMoeD1jYXJhdCx5PXByaWNlKSkrCiAgZ2VvbV9oZXgoKQpnZ3NhdmUoImRpYW1vbmRzLnBuZyIpCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmBgYAoKYGBge3J9CnN0dWRlbnRzPC1yZWFkX2NzdigiaHR0cHM6Ly9wb3MuaXQvcjRkcy1zdHVkZW50cy1jc3YiKQoKc3R1ZGVudHMKCnN0dWRlbnRzPC1yZWFkX2NzdigiaHR0cHM6Ly9wb3MuaXQvcjRkcy1zdHVkZW50cy1jc3YiLG5hPWMoIk4vQSIsIiIpKQoKc3R1ZGVudHMgPC0gc3R1ZGVudHMgfD4KICByZW5hbWUoc3R1ZGVudF9pZCA9IGBTdHVkZW50IElEYCwKICAgICAgICAgZnVsbF9uYW1lID0gYEZ1bGwgTmFtZWApCgpzdHVkZW50cyA8LSBzdHVkZW50cyB8PgogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgfD4KICBtdXRhdGUobWVhbF9wbGFuID0gZmFjdG9yKG1lYWxfcGxhbiksCiAgICAgICAgIGFnZSA9IHBhcnNlX251bWJlcihpZl9lbHNlKGFnZSA9PSAiZml2ZSIsICI1IiwgYWdlKSkpCiAgICAgICAgIApgYGAKCmBgYHtyfQpyZWFkX2NzdigiVGhlIGZpcnN0IGxpbmUgb2YgbWV0YWRhdGEKICAgICAgICAgIFRoZSBzZWNvbmQgbGluZSBvZiBtZXRhIGRhYXQKICAgICAgICAgIGEsYixjCiAgICAgICAgICAxLDIsMwogICAgICAgICAgNCw1LDYiLAogICAgICAgICAgc2tpcD0yKQoKcmVhZF9jc3YoCiAgIiMgQSBjb21tZW50IEkgd2FudCB0byBza2lwCiAgeCx5LHoKICAxLDIsMyIsCiAgY29tbWVudD0iIyIKKQoKcmVhZF9jc3YoCiAgIjEsMiwzCiAgIDQsNSw2Iixjb2xfbmFtZXM9IEZBTFNFKQoKcmVhZF9jc3YoCiAgIjEsMiwzCiAgIDQsNSw2Iixjb2xfbmFtZXM9IGMoIngiLCJ5IiwieiIpKQoKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDUzCnE1MzwtIkkgd291bGQgdXNlIHRoZSByZWFkX2RlbGltKCkgZnVuY3Rpb24gdG8gcHVsbCBpbiBkYXRhIHRoYXQgaXMgc2VwYXJhdGVkIHdpdGggdGhlIHwgc3ltYm9sLiIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDU0CnE1NDwtInJlYWRfY3N2KCkgYW5kIHJlYWRfdHN2KCkgc2hhcmUgbWFueSBhcmd1bWVudHMuIFNwZWNpZmljYWxseSB0aGV5IHNoYXJlIGNvbF9uYW1lcywgY29sX3R5cGVzLCBpZCBldGMuLi4iCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA1NQpxNTU8LSJUaGUgbW9zdCBpbXBvcnRhbnQgYXJndW1lbnQgZm9yIHJlYWRfZndmKCkgaXMgdGhlIHdpZHRocygpIGZ1bmN0aW9uIHNpbmNlIHRoZSBmaWVsZCBzaXplIG11c3QgYmUgc3BlY2lmaWVkLiIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDU2CmxpYnJhcnkocmVhZHIpCgpxNTYgPC0gcmVhZF9jc3YoIngseVxuMSwnYSxiJyIsIHF1b3RlID0gIiciKQoKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDU3CnJlYWRfY3N2KCJhLGIvbiAKICAgICAgICAgIDEyLDMvbiAKICAgICAgICAgIDQsNSw2IikKCnJlYWRfY3N2KCJhLGIsYy9uCiAgICAgICAgICAxLDIvbgogICAgICAgICAgMSwyLDMsNCIpCgpyZWFkX2NzdigiYSxiXG4xIikKCnJlYWRfY3N2KCdhLGJcbiIxLDIiLDNcbmEsYicpCgpyZWFkX2NzdjIoImE7XG4xOzMiKQoKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDU4CmFubm95aW5nIDwtIHRpYmJsZSgKICAnMScgPSAxOjEwLAogICcyJyA9IGFzLm51bWVyaWMoJzEnKSAqIDIgKyBybm9ybSgxMCkKKQoKYW5ub3lpbmcgfD4gCiAgc2VsZWN0KDEpCgphbm5veWluZyB8PiAKICBnZ3Bsb3QoYWVzKHg9YDFgLHk9YDJgKSkrCiAgZ2VvbV9wb2ludCgpCgphbm5veWluZyA8LSBhbm5veWluZyB8PgogIG11dGF0ZShgM2AgPSBgMmAgLyBgMWApCgphbm5veWluZyB8PiAKICByZW5hbWUoYE9uZWA9YDFgLAogICAgICAgICBgVHdvYD1gMmAsCiAgICAgICAgIGBUaHJlZWA9YDNgKQpgYGAKCmBgYHtyfQpyZWFkX2NzdigiCiAgICAgICAgIGxvZ2ljYWwubnVtZXJpYyxkYXRlLHN0cmluZwogICAgICAgICBUUlVFLDEsMjAyMS0wMS0xNSxhYmMKICAgICAgICAgZmFsc2UsNC41LDIwMjEtMDItMTUsZGVmCiAgICAgICAgIFQsSW5mLDIwMjEtMDItMTYsZ2hpIikKYGBgCgpgYGB7cn0Kc2ltcGxlX2NzdiA8LSAiCngKMTAKLgoyMAozMCIKCmRmPC1yZWFkX2NzdigKICBzaW1wbGVfY3N2LAogIGNvbF90eXBlcyA9IGxpc3QoeD1jb2xfZG91YmxlKCkpKQoKcHJvYmxlbXMoZGYpCgpyZWFkX2NzdigKICBzaW1wbGVfY3N2LG5hPSIuIikKYGBgCgpgYGB7cn0KYW5vdGhlcl9jc3YgPC0gIgp4LHksegoxLDIsMyIKCnJlYWRfY3N2KAogIGFub3RoZXJfY3N2LAogIGNvbF90eXBlcyA9IGNvbHMoLmRlZmF1bHQ9Y29sX2NoYXJhY3RlcigpKQopCgpyZWFkX2NzdigKICBhbm90aGVyX2NzdiwKICBjb2xfdHlwZXMgPSBjb2xzX29ubHkoeD1jb2xfY2hhcmFjdGVyKCkpCikKYGBgCgpgYGB7cn0Kc2FsZXNfZmlsZXMgPC0gYygKICAiaHR0cHM6Ly9wb3MuaXQvcjRkcy0wMS1zYWxlcyIsCiAgImh0dHBzOi8vcG9zLml0L3I0ZHMtMDItc2FsZXMiLAogICJodHRwczovL3Bvcy5pdC9yNGRzLTAzLXNhbGVzIgopCnJlYWRfY3N2KHNhbGVzX2ZpbGVzLGlkPSJmaWxlIikKCnNhbGVzX2ZpbGVzIDwtIGxpc3QuZmlsZXMoImRhdGEiLHBhdHRlcm4gPSAic2FsZXNcXC5jc3YkIixmdWxsLm5hbWVzID0gVFJVRSkKc2FsZXNfZmlsZXMKYGBgCgpgYGB7cn0Kd3JpdGVfY3N2KHN0dWRlbnRzLCJzdHVkZW50cy5jc3YiKQpgYGAKCmBgYHtyfQp3cml0ZV9yZHMoc3R1ZGVudHMsInN0dWRlbnRzLnJkcyIpCnJlYWRfcmRzKCJzdHVkZW50cy5yZHMiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGFycm93KQp3cml0ZV9wYXJxdWV0KHN0dWRlbnRzLCJzdHVkZW50cy5wYXJxdWV0IikKcmVhZF9wYXJxdWV0KCJzdHVkZW50cy5wYXJxdWV0IikKYGBgCgpgYGB7cn0KI0RhdGEgRW50cnkKdGliYmxlKAogIHg9YygxLDIsNSksCiAgeT1jKCJoIiwibSIsImciKSwKICB6PWMoMC4wOCwwLjgzLDAuNjApCikKCnRyaWJibGUoCiAgfngsfnksfnosCiAgMSwiaCIsMC4wOCwKICAyLCJtIiwwLjgzLAogIDUsImciLDAuNjAKKQpgYGAKCiMgQ2hhcHRlciA4OiBXb3JrZmxvdyBHZXR0aW5nIEhlbHAKYGBge3J9Cnk8LTE6NAptZWFuKHkpCmBgYAoKYGBge3J9CmxpYnJhcnkocmVwcmV4KCkpCnk8LSAxOjQKbWVhbih5KQoKcmVwcmV4KG10Y2FycykKYGBgCgpgYGB7cn0KdGlkeXZlcnNlX3VwZGF0ZSgpCmBgYAoKYGBge3J9CmRwdXQobXRjYXJzKQpgYGAKCmBgYHtyfQpyZXByZXgobXRjYXJzPC1zdHJ1Y3R1cmUobGlzdChtcGcgPSBjKDIxLCAyMSwgMjIuOCwgMjEuNCwgMTguNywgMTguMSwgMTQuMywgCjI0LjQsIDIyLjgsIDE5LjIsIDE3LjgsIDE2LjQsIDE3LjMsIDE1LjIsIDEwLjQsIDEwLjQsIDE0LjcsIDMyLjQsIAozMC40LCAzMy45LCAyMS41LCAxNS41LCAxNS4yLCAxMy4zLCAxOS4yLCAyNy4zLCAyNiwgMzAuNCwgMTUuOCwgCjE5LjcsIDE1LCAyMS40KSwgY3lsID0gYyg2LCA2LCA0LCA2LCA4LCA2LCA4LCA0LCA0LCA2LCA2LCA4LCAKOCwgOCwgOCwgOCwgOCwgNCwgNCwgNCwgNCwgOCwgOCwgOCwgOCwgNCwgNCwgNCwgOCwgNiwgOCwgNCksIAogICAgZGlzcCA9IGMoMTYwLCAxNjAsIDEwOCwgMjU4LCAzNjAsIDIyNSwgMzYwLCAxNDYuNywgMTQwLjgsIAogICAgMTY3LjYsIDE2Ny42LCAyNzUuOCwgMjc1LjgsIDI3NS44LCA0NzIsIDQ2MCwgNDQwLCA3OC43LCA3NS43LCAKICAgIDcxLjEsIDEyMC4xLCAzMTgsIDMwNCwgMzUwLCA0MDAsIDc5LCAxMjAuMywgOTUuMSwgMzUxLCAxNDUsIAogICAgMzAxLCAxMjEpLCBocCA9IGMoMTEwLCAxMTAsIDkzLCAxMTAsIDE3NSwgMTA1LCAyNDUsIDYyLCA5NSwgCiAgICAxMjMsIDEyMywgMTgwLCAxODAsIDE4MCwgMjA1LCAyMTUsIDIzMCwgNjYsIDUyLCA2NSwgOTcsIDE1MCwgCiAgICAxNTAsIDI0NSwgMTc1LCA2NiwgOTEsIDExMywgMjY0LCAxNzUsIDMzNSwgMTA5KSwgZHJhdCA9IGMoMy45LCAKICAgIDMuOSwgMy44NSwgMy4wOCwgMy4xNSwgMi43NiwgMy4yMSwgMy42OSwgMy45MiwgMy45MiwgMy45MiwgCiAgICAzLjA3LCAzLjA3LCAzLjA3LCAyLjkzLCAzLCAzLjIzLCA0LjA4LCA0LjkzLCA0LjIyLCAzLjcsIDIuNzYsIAogICAgMy4xNSwgMy43MywgMy4wOCwgNC4wOCwgNC40MywgMy43NywgNC4yMiwgMy42MiwgMy41NCwgNC4xMQogICAgKSwgd3QgPSBjKDIuNjIsIDIuODc1LCAyLjMyLCAzLjIxNSwgMy40NCwgMy40NiwgMy41NywgMy4xOSwgCiAgICAzLjE1LCAzLjQ0LCAzLjQ0LCA0LjA3LCAzLjczLCAzLjc4LCA1LjI1LCA1LjQyNCwgNS4zNDUsIDIuMiwgCiAgICAxLjYxNSwgMS44MzUsIDIuNDY1LCAzLjUyLCAzLjQzNSwgMy44NCwgMy44NDUsIDEuOTM1LCAyLjE0LCAKICAgIDEuNTEzLCAzLjE3LCAyLjc3LCAzLjU3LCAyLjc4KSwgcXNlYyA9IGMoMTYuNDYsIDE3LjAyLCAxOC42MSwgCiAgICAxOS40NCwgMTcuMDIsIDIwLjIyLCAxNS44NCwgMjAsIDIyLjksIDE4LjMsIDE4LjksIDE3LjQsIDE3LjYsIAogICAgMTgsIDE3Ljk4LCAxNy44MiwgMTcuNDIsIDE5LjQ3LCAxOC41MiwgMTkuOSwgMjAuMDEsIDE2Ljg3LCAKICAgIDE3LjMsIDE1LjQxLCAxNy4wNSwgMTguOSwgMTYuNywgMTYuOSwgMTQuNSwgMTUuNSwgMTQuNiwgMTguNgogICAgKSwgdnMgPSBjKDAsIDAsIDEsIDEsIDAsIDEsIDAsIDEsIDEsIDEsIDEsIDAsIDAsIDAsIDAsIDAsIAogICAgMCwgMSwgMSwgMSwgMSwgMCwgMCwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMCwgMSksIGFtID0gYygxLCAKICAgIDEsIDEsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDEsIDEsIDEsIAogICAgMCwgMCwgMCwgMCwgMCwgMSwgMSwgMSwgMSwgMSwgMSwgMSksIGdlYXIgPSBjKDQsIDQsIDQsIDMsIAogICAgMywgMywgMywgNCwgNCwgNCwgNCwgMywgMywgMywgMywgMywgMywgNCwgNCwgNCwgMywgMywgMywgCiAgICAzLCAzLCA0LCA1LCA1LCA1LCA1LCA1LCA0KSwgY2FyYiA9IGMoNCwgNCwgMSwgMSwgMiwgMSwgNCwgCiAgICAyLCAyLCA0LCA0LCAzLCAzLCAzLCA0LCA0LCA0LCAxLCAyLCAxLCAxLCAyLCAyLCA0LCAyLCAxLCAKICAgIDIsIDIsIDQsIDYsIDgsIDIpKSwgcm93Lm5hbWVzID0gYygiTWF6ZGEgUlg0IiwgIk1hemRhIFJYNCBXYWciLCAKIkRhdHN1biA3MTAiLCAiSG9ybmV0IDQgRHJpdmUiLCAiSG9ybmV0IFNwb3J0YWJvdXQiLCAiVmFsaWFudCIsIAoiRHVzdGVyIDM2MCIsICJNZXJjIDI0MEQiLCAiTWVyYyAyMzAiLCAiTWVyYyAyODAiLCAiTWVyYyAyODBDIiwgCiJNZXJjIDQ1MFNFIiwgIk1lcmMgNDUwU0wiLCAiTWVyYyA0NTBTTEMiLCAiQ2FkaWxsYWMgRmxlZXR3b29kIiwgCiJMaW5jb2xuIENvbnRpbmVudGFsIiwgIkNocnlzbGVyIEltcGVyaWFsIiwgIkZpYXQgMTI4IiwgIkhvbmRhIENpdmljIiwgCiJUb3lvdGEgQ29yb2xsYSIsICJUb3lvdGEgQ29yb25hIiwgIkRvZGdlIENoYWxsZW5nZXIiLCAiQU1DIEphdmVsaW4iLCAKIkNhbWFybyBaMjgiLCAiUG9udGlhYyBGaXJlYmlyZCIsICJGaWF0IFgxLTkiLCAiUG9yc2NoZSA5MTQtMiIsIAoiTG90dXMgRXVyb3BhIiwgIkZvcmQgUGFudGVyYSBMIiwgIkZlcnJhcmkgRGlubyIsICJNYXNlcmF0aSBCb3JhIiwgCiJWb2x2byAxNDJFIiksIGNsYXNzID0gImRhdGEuZnJhbWUiKSkKYGBgCgojIyBQYXJ0IDI6IFZpc3VhbGl6ZQojIENoYXB0ZXIgOTogTGF5ZXJzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpgYGB7cn0KbXBnCmBgYAoKYGBge3J9CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3ksY29sb3I9Y2xhc3MpKSsKICBnZW9tX3BvaW50KCkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3ksc2hhcGU9Y2xhc3MpKSsKICBnZW9tX3BvaW50KCkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3ksc2l6ZT1jbGFzcykpKwogIGdlb21fcG9pbnQoKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSxhbHBoYT1jbGFzcykpKwogIGdlb21fcG9pbnQoKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fcG9pbnQoY29sb3I9ImJsdWUiKQpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDU5CmdncGxvdChtcGcsYWVzKHg9aHd5LHk9ZGlzcGwsY29sb3I9J3BpbmsnKSkrCiAgZ2VvbV9wb2ludChzaGFwZT0xNykKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2MAojZ2dwbG90KG1wZyxhZXMoY29sb3I9J2JsdWUnKSkgKyBnZW9tX3BvaW50KGFlcyh4PWRpc3BsLHk9aHd5KSkKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSxjb2xvcj0ncGluaycpKStnZW9tX3BvaW50KGNvbG9yPSdibHVlJykKcTYwPC0iVGhlIHBvaW50cyBhcmUgbm90IGJsdWUgYmVjYXVzZSB0aGUgeCBhbmQgeSBuZWVkIHRvIGJlIGRlZmluZWQgd2l0aGluIHRoZSBnZ3Bsb3QoKSBmdW5jdGlvbiBjYWxsIGFuZCB0aGUgY29sb3IgbmVlZHMgdG8gYmUgZGVmaW5lZCB3aXRoaW4gdGhlIGdlb21fcG9pbnQoKSBmdW5jdGlvbi4iCgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDYxCnE2MTwtIlRoZSBzdHJva2UgYWVzdGhldGljIGRldGVybWluZXMgdGhlIHRoaWNrbmVzcyBvZiB0aGUgdmlzdWFsIGF0dHJpYnV0ZS4gVGhlIG1vc3QgY29tbW9uIGdlb21zIGFyZSBzY2F0dGVycGxvdHMsIGxpbmUgcGxvdHMsIGFuZCBiYXIgY2hhcnRzLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2MgpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5LGNvbG9yPSdwaW5rJykpK2dlb21fcG9pbnQoY29sb3I9bXBnJGRpc3BsKQpxNjI8LSJJZiBhbiBhZXN0aGV0aWMgaXMgbWFwcGVkIHRvIHNvbWV0aGluZyB0aGF0IGlzIG5vdCBhIHZhcmlhYmxlLCB0aGVuIGFuIGVycm9yIHdpbGwgb2NjdXIuIgpgYGAKCmBgYHtyfQpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5KSkrCiAgZ2VvbV9wb2ludCgpCgpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5KSkrCiAgZ2VvbV9zbW9vdGgoKSsKICBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSxzaGFwZT1kcnYpKSsKICBnZW9tX3Ntb290aCgpCgpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5LGxpbmV0eXBlPWRydikpKwogIGdlb21fc21vb3RoKCkKYGBgCgpgYGB7cn0KZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSxjb2xvcj1kcnYpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgoYWVzKGxpbmV0eXBlPWRydikpCmBgYAoKYGBge3J9CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9wb2ludCgKICAgIGRhdGEgPSBtcGcgfD4gCiAgICAgIGZpbHRlcihjbGFzcz09IjJzZWF0ZXIiKSwKICAgIHNoYXBlPSJjaXJjbGUgb3BlbiIsc2l6ZT0zLGNvbG9yPSJyZWQiCiAgKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobXBnLGFlcyh4PWh3eSkpKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMikKCmdncGxvdChtcGcsYWVzKHg9aHd5KSkrCiAgZ2VvbV9kZW5zaXR5KCkKCmdncGxvdChtcGcsYWVzKHg9aHd5KSkrCiAgZ2VvbV9ib3hwbG90KCkKCgpgYGAKYGBge3J9CmxpYnJhcnkoZ2dyaWRnZXMpCgpnZ3Bsb3QobXBnLGFlcyh4PWh3eSx5PWRydixmaWxsPWRydixjb2xvcj1kcnYpKSsKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGFscGhhPTAuNSxzaG93LmxlZ2VuZCA9IEZBTFNFKQpgYGAKYGBge3J9CiMgUXVlc3Rpb24gNjMKcTYzPC0iZ2VvbV9saW5lKCksIGdlb21fYm94cGxvdCgpLCBnZW9tX2hpc3RvZ3JhbSgpLCBnZW9tX2FyZWEoKSIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2NApnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5KSkrCiAgZ2VvbV9zbW9vdGgoYWVzKGNvbG9yPWRydikpCnE2NDwtIlRoZSBsZWdlbmQgYXJndWVtZW50IGRldGVybWluZSBpZiBhIGxlZ2VuZCBzaG91bGQgYmUgYWRkZWQgdG8gdGhlIGdyYXBoLiBJZiBJIHJlbW92ZSBpdCwgdGhlIGxlZ2VuZCBpcyBhZGRlZCBiYWNrIGluLiBXZSB1c2VkIHRoaXMgZWFybGllciBzaW5jZSB3ZSBtb3JlIGZvY3VzZWQgb24gdGhlIHNwbGl0dGluZyB0aGUgZGF0YSBpbnRvIHRoZSB0aHJlZSBkcnYgZ3JvdXBzLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2NQpxNjU8LSJUaGUgc2UgYXJndW1lbnQgZGV0ZXJtaW5lcyBpZiBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgc2hvdWxkIGJlIGFkZGVkLiIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDY2CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgoc2U9RkFMU0UpCgpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsLHk9aHd5LHNoYXBlPWRydikpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChzZT1GQUxTRSkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3ksY29sb3I9ZHJ2KSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKHNlPUZBTFNFKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWRydikpKwogIGdlb21fc21vb3RoKHNlPUZBTFNFKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWRydikpKwogIGdlb21fc21vb3RoKHNlPUZBTFNFLGFlcyhsaW5ldHlwZT1kcnYpKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWRydixmaWxsPSd3aGl0ZScpLGZpbGw9J3doaXRlJykrCiAgZ2VvbV9wb2ludChzaGFwZT0xLGNvbG9yPSd3aGl0ZScsc2l6ZT0zLHN0cm9rZT0yKQoKYGBgCgpgYGB7cn0KZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fcG9pbnQoKSsKICBmYWNldF9ncmlkKGRydn5jeWwsc2NhbGVzPSJmcmVlX3kiKQpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDY2CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgZmFjZXRfd3JhcCh+Y3R5KQpxNjY8LSJGYWNldGluZyBhIGNvbnRpbmlvdXMgdmFyaWFibGUgd2lsbCBtYWtlIGEgdmlzdWFsIGZvciBlYWNoIHVuaXF1ZSB2YWx1ZSIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2NwpnZ3Bsb3QobXBnKSsKICBnZW9tX3BvaW50KGFlcyh4PWRpc3BsLHk9Y3lsKSkrCiAgZmFjZXRfZ3JpZChkcnZ+Y3lsKQpxNjc8LSJUaGUgZW1wdHkgY2hhcnRzIHJlcHJlc2VudCB2YWx1ZSBjb21iaW5hdGlvbnMgdGhhdCBkb24ndCBleGlzdCBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA2OApnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGZhY2V0X2dyaWQoZHJ2fi4pCgpnZ3Bsb3QobXBnKSsKICBnZW9tX3BvaW50KGFlcyh4PWRpc3BsLHk9aHd5KSkrCiAgZmFjZXRfZ3JpZChjeWx+LikKCnE2ODwtIlRoZXNlIHBsb3RzIGZhY2V0IGJ5IGRydiBhbmQgY3lsLiBUaGUgLiBwb3NpdGlvbiByZWxhdGl2ZSB0byB+IGRldGVybWluZXMgdGhlIHBsb3Qgb3JpZW50YXRpb24uIgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDY5CmdncGxvdChtcGcpKwogIGdlb21fcG9pbnQoYWVzKHg9ZGlzcGwseT1od3kpKSsKICBmYWNldF93cmFwKH5jbGFzcyxucm93PTIpCnE2OTwtIk9uZSBhZHZhbnRhZ2Ugb2YgZmFjZXRpbmcgaXMgdGhhdCBpdCdzIGVhc2llciB0byBldmFsdWF0ZSBlYWNoIGdyb3VwaW5nLiBUaGUgZGlzZHZhbnRhZ2UgaXMgdGhhdCBpdCdzIGhhcmRlciB0byBjb21wYXJlIGJldHdlZW4gZ3JvdXBzLiBJZiB3ZSBoYXZlIGEgdmVyeSBsYXJnZSBkYXRhc2V0LCBmYWNldGluZyB3b3VsZCBiZSB0aGUgYmVzdCBvcHRpb24gc2luY2Ugd2lsbCBiZSBhYmxlIHRvIHNwbGl0IHRoZSBkYXRhIGludG8gc21hbGwgZ3JvdXBpbmdzLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA3MApxNzA8LSJucm93IGRldGVybWluZXMgdGhlIG51bWJlciBvZiByb3dzLCBuY29scyBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgY29sdW1ucy4gQWRkaXRpb25hbCBvcHRpb25zIGluY2x1ZGUgc2NhbGVzLCBsYWJlbGxlciBldGMuIGZhY2V0X2dyaWQoKSBkb2Vzbid0IG5lZWQgdGhlIHJvd3Mgb3IgY29sdW1ucyBhcmd1bWVudCBiZWNhdXNlIHdlIGFyZSBmYWNldGluZyBvZiBjb250aW5pb3VzIHZhcmlhYmxlcy4iCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA3MQpnZ3Bsb3QobXBnLGFlcyh4PWRpc3BsKSkrCiAgZ2VvbV9oaXN0b2dyYW0oKSsKICBmYWNldF9ncmlkKGRydn4uKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfZ3JpZCgufmRydikKCnE3MTwtIlRoZSBmaXJzdCBwbG90IGlzIGVhc2llciB0byByZWFkIGJlY2F1c2UgZWFjaCBwbG90IHNoYXJlcyB0aGUgc2FtZSB4LWF4aXMgcmFuZ2UgLyB0aGUgcGxvdHMgYXJlIHN0YWNrZWQgb24gdG9wIG9mIGVhY2ggb3RoZXIuIEl0J3MgbXVjaCBoYXJkZXIgdG8gY29tcGFyZSB0aGUgcGxvdHMgd2hlbiB0aGV5IGFyZSBzaWRlIGJ5IHNpZGUuIgoKCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA3MgpnZ3Bsb3QobXBnKSsKICBnZW9tX3BvaW50KGFlcyh4PWRpc3BsLHk9aHd5KSkrCiAgZmFjZXRfZ3JpZChkcnZ+LikKCmdncGxvdChtcGcpKwogIGdlb21fcG9pbnQoYWVzKHg9ZGlzcGwseT1od3kpKSsKICBmYWNldF93cmFwKH5kcnYsZGlyPSJoIikKCnE3MjwtIldoZW4gc3dpdGNoaWduIGZyb20gZmFjZXQgd3JhcCB0byBmYWNldCBncmlkLCB0aGUgZ3JhcGggb3JpZW50YXRpb24gY2hhbmdlcyBmcm9tIGhvcml6b250YWwgdG8gdmVydGljYWwuIgpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9Y3V0KSkrZ2VvbV9iYXIoKQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWN1dCx5PWFmdGVyX3N0YXQocHJvcCksZ3JvdXA9MSkpK2dlb21fYmFyKCkKCmdncGxvdChkaWFtb25kcykgKwogIHN0YXRfc3VtbWFyeSgKICAgIGFlcyh4PWN1dCwgeT1kZXB0aCksCiAgICBmdW4ubWluPW1pbixmdW4ubWF4PW1heCwKICAgIGZ1bj1tZWRpYW4KICApCmBgYApgYGB7cn0KcTc0PC0iVGhlIGRlZmF1bHQgZ2VvbSBhc3NvY2lhdGVkIHdpdGggc3RhdF9zdW1tYXJ5KCkgaW4gUiBpcyBhIGNyb3NzIGJhci4gIgoKZ2dwbG90KGRpYW1vbmRzKSArCiAgc3RhdF9zdW1tYXJ5KAogICAgYWVzKHg9Y3V0LCB5PWRlcHRoKSwKICAgIGZ1bi5taW49bWluLGZ1bi5tYXg9bWF4LAogICAgZnVuPW1lZGlhbgogICkKCmdncGxvdChkaWFtb25kcywgYWVzKHggPSBjdXQsIHkgPSBkZXB0aCkpICsKICBnZW9tX3BvaW50KHN0YXQgPSAic3VtbWFyeSIsIGZ1biA9ICJtZWRpYW4iLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fbGluZXJhbmdlKHN0YXQgPSAic3VtbWFyeSIsIGZ1bi5taW4gPSAibWluIiwgZnVuLm1heCA9ICJtYXgiLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIikKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDc1CnE3NTwtIlRoZSBkaWZmZXJlbmNlIGJldHdlZW4gZ2VvbV9jb2woKSBhbmQgZ2VvbV9iYXIoKSBpcyB0aGF0IGdlb21fY29sKCkgaXMgdXNlZCB3aGVuIGJvdGggeCBhbmQgeSBhc2V0aGV0aWNzIGFyZSBrbm93biBhbmQgZ2VvbV9iYXIoKSBpcyB1c2VkIHR5cGljYWxseSB3aGVuIG9ubHkgdGhlIHggYXNldGhldGljIGlzIGtub3duLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA3NgpxNzY8LSJTb21lIG9mIHRoZSBjb21tb24gcGFpcnMgYXJlIHNjYXR0ZXJwbG90cyAoZ2VvbV9wb2ludCwgc3RhdF9pZGVudGl0eSksIGxpbmUgY2hhcnRzIChnZW9tX2xpbmUsIHN0YXRfaWRlbnRpdHkpLCBhbmQgQmFyIENoYXJ0cyAoZ2VvbV9iYXIoKSwgc3RhdF9jb3VudCkuIFRoZXNlIHBhaXJzIGFyZSBhbGwgc2ltaWxhciBiZWNhdXNlIHRoZXkgcGVyZnJvbSBmdW5jdGlvbnMgdG8gY2FsY3VsYXRlIGFuIGFkZGl0aW9uYWwgc3RhdGlzdGljIG9yIGVzdGltYXRlcy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gNzcKcTc3PC0ic3RhdF9zbW9vdGggY2FsY3VsYXRlcyBmaXR0ZWQgdmFsdWVzIGZyb20gYSByZWdyZXNzaW9uIG1vZGVsIHRoYXQgdXNlcyB0aGUgeCBhbmQgeSB2YXJpYWJsZXMuIFNvbWUgY29tbW9uIGFyZ3VtZW50cyBpbmNsdWRlIHRoZSByZWdyZXNzaW9uIHR5cGUsIGZvcm11bGEsIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIG9yIGRpc3RyaWJ1dGlvbiBmYW1pbHkuIgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gNzgKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWN1dCx5PWFmdGVyX3N0YXQocHJvcCkpKSsKICBnZW9tX2JhcigpCgpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9Y3V0LGZpbGw9Y29sb3IseT1hZnRlcl9zdGF0KHByb3ApKSkrCiAgZ2VvbV9iYXIoKQoKcTc4PC0iVGhlIGdyb3VwIGFyZ3VtZW50IGluIHByb3BvcnRpb24gcGxvdHMgbXVzdCBiZSBzcGVjaWZpZWQgc28gdGhhdCB0aGUgcHJvcG9ydGlvbiBpcyBjYWxjdWxhdGVkIHByb3Blcmx5IHdoZW4gY29uc2lkZXJpbmcgZWFjaCBjYXRlZ29yeS4gSWYgdGhlIGdyb3VwIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBncmFwaCB3aWxsIGluY29ycmVjdGx5IGNhbGN1YXRlIHRoZSBwcm9wb3J0aW9uLiIKYGBgCgpgYGB7cn0KZ2dwbG90KG1wZyxhZXMoeD1kcnYsY29sb3I9ZHJ2KSkrCiAgZ2VvbV9iYXIoKQoKZ2dwbG90KG1wZyxhZXMoeD1kcnYsZmlsbD1kcnYpKSsKICBnZW9tX2JhcigpCgpnZ3Bsb3QobXBnLGFlcyh4PWRydixmaWxsPWNsYXNzKSkrCiAgZ2VvbV9iYXIoKQoKZ2dwbG90KG1wZyxhZXMoeD1kcnYsZmlsbD1jbGFzcykpKwogIGdlb21fYmFyKGFscGhhPTEvNSxwb3NpdGlvbj0iaWRlbnRpdHkiKQoKZ2dwbG90KG1wZyxhZXMoeD1kcnYsY29sb3I9Y2xhc3MpKSsKICBnZW9tX2JhcihmaWxsPU5BLHBvc2l0aW9uID0gImlkZW50aXR5IikKCmdncGxvdChtcGcsYWVzKHg9ZHJ2LGZpbGw9Y2xhc3MpKSsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikKCmdncGxvdChtcGcsYWVzKHg9ZHJ2LGZpbGw9Y2xhc3MpKSsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpCmBgYAoKYGBge3J9CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiKQpgYGAKCmBgYHtyfQojUXVlc3Rpb24gNzgKZ2dwbG90KG1wZyxhZXMoeD1jdHkseT1od3kpKSsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiLGFscGhhPTAuNSkKcTc4PC0iVGhlIHByb2JsZW0gd2l0aCB0aGlzIHBsb3QgaXMgdGhhdCB0aGUgcG9pbnRzIG92ZXJsYXAgZWFjaCBvdGhlci4gVGhlIGppdHRlciBmdW5jdGlvbiBwcm9kdWNlcyBzb21lIHJhbmRvbm5lc3MgaW4gb3JkZXIgdG8gc2VlIHRoZSBwb2ludHMuICIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDc5CnE3OTwtIlRoZXNlIHBsb3RzIHByb2R1Y2UgdGhlIHNhbWUgY2hhcnQuIFRoZSBwb3NpdGlvbj1pZGVudGl0eSBhcmd1bWVudCBwbG90cyB0aGUgcG9pbnRzIHRoZSBzYW1lIHdheSBhcyB0aGUgZGVmYXVsdCBzZXR0aW5nLiIgCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJpZGVudGl0eSIpCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA4MApxODA8LSJUaGUgd2lkdGggYW5kIGhlaWdodCBwYXJhbWV0ZXJzIGNvbnRyb2wgdGhlIGFtb3VudCBvZiBqaXR0ZXJpbmcuIgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gODEKcTgxPC0iR2VvbSBjb3VudCBjcmVhdGVzIGFuIGFzZXRoZXRpYyBiYXNlZCB1cG9uIHBvaW50IHNpemUgd2hpbGUgZ2VvbSBqaXR0ZXIgY3JlYXRlcyBhbiBhc2V0aGV0aWMgdGhhdCBzbGlnaHQgcmFuZG9tbmVzcyB0byB0aGUgcG9pbnRzLiIKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSkpKwogIGdlb21fY291bnQoKQpgYGAKCmBgYHtyfQojUXVlc3Rpb24gODEKcTgxPC0iVGhlIGRlZmF1bHQgcG9zaXRpb24gaXMgZG9kZ2UyIHdoaWNoIHBsb3RzIGVhY2ggYm94IGFuZCB3aGlza2VyIHBsb3QgbmV4dCB0byBlYWNoIG90aGVyLiIKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWRydikpKwogIGdlb21fYm94cGxvdChwb3NpdGlvbj0iZG9kZ2UiKQoKYGBgCgpgYGB7cn0Kbno8LW1hcF9kYXRhKCJueiIpCgpnZ3Bsb3QobnosYWVzKHg9bG9uZyx5PWxhdCxncm91cD1ncm91cCkpKwogIGdlb21fcG9seWdvbihmaWxsPSJ3aGl0ZSIsY29sb3I9ImJsYWNrIikKCmdncGxvdChueixhZXMoeD1sb25nLHk9bGF0LGdyb3VwPWdyb3VwKSkrCiAgZ2VvbV9wb2x5Z29uKGZpbGw9IndoaXRlIixjb2xvcj0iYmxhY2siKSsKICBjb29yZF9xdWlja21hcCgpCgpiYXIgPC0gZ2dwbG90KGRhdGE9ZGlhbW9uZHMpKwogIGdlb21fYmFyKAogICAgbWFwcGluZz1hZXMoeD1jbGFyaXR5LGZpbGw9Y2xhcml0eSksCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgd2lkdGggPSAxCiAgKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkKCmJhciArIGNvb3JkX2ZsaXAoKQpiYXIgKyBjb29yZF9wb2xhcigpCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA4MQpiYXJfY2hhcnQgPC0gZ2dwbG90KG1wZywgYWVzKHggPSBkcnYsIGZpbGwgPSB0cmFucykpICsKICBnZW9tX2JhcigpICsKICBsYWJzKHRpdGxlID0gIlN0YWNrZWQgQmFyIENoYXJ0IikKCnBpZV9jaGFydCA8LSBiYXJfY2hhcnQgKyBjb29yZF9wb2xhcigpCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA4MgpxODI8LSJUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjb29yZF9xdWlja21hcCgpIGFuZCBjb29yZF9tYXAoKSBpcyB0aGF0IGNvb3JkX3F1aWNrbWFwKCkgaXMgYSBjb29yZG5pYXRlIHN5c3RlbSB0aGF0IHByb3ZpZGVzIGEgZ29vZCBwcm9qZWN0aW9uIHF1aWNrbHkgZm9yIHggYW5kIHkgY29vcmRpbmF0ZXMgd2hpbGUgdGhlIGNvb3JkX21hcCgpIGZ1bmN0aW9uIHVzZXMgdGhlIG1lcmNhdG9yIHByb2plY3Rpb24uIgpgYGAKCmBgYHtyfQojUXVlc3Rpb24gODMKcTgzPC1nZ3Bsb3QoZGF0YT1tcGcsbWFwcGluZz1hZXMoeD1jdHkseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9hYmxpbmUoKSsKICBjb29yZF9maXhlZCgpCnE4MzwtIkZyb20gdGhpcyBwbG90LCB3ZSBjYW4gc2VlIHRoYXQgaHd5IG1wZyBpcyBhbHdheXMgaGlnaCB0aGFuIGNpdHkgbXBnLiBUaGUgY29vcmRfZml4ZWQgZnVuY3Rpb24gZW5zdXJlcyB0aGF0IHRoZSB4LWF4aXMgYW5kIHktYXhpcyBoYXMgdGhlIHNhbWUgY29vcmRpbmF0ZSBzY2FsZS4gVGhlIGdlb21fYWJsaW5lIGFkZGVzIGEgNDUgZGVncmVlIGFuZ2xlIHRoYXQgaGVscHMgYWRkIHBlcnNwZWN0aXZlLiAiCmBgYAoKIyBDaGFwdGVyIDEwOiBFeHBsb3JpdG9yeSBEYXRhIEFuYWx5c2lzCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgpgYGB7cn0KZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWNhcmF0KSkrCiAgZ2VvbV9oaXN0b2dyYW0oYmlucz0xMCkKCnNtYWxsZXIgPC0gZGlhbW9uZHMgfD4gCiAgICAgICAgICAgICAgZmlsdGVyKGNhcmF0PDMpCgpnZ3Bsb3Qoc21hbGxlcixhZXMoeD1jYXJhdCkpKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0uMDEpCmBgYAoKYGBge3J9CmdncGxvdChkaWFtb25kcyxhZXMoeD15KSkrCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MC41KQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PXkpKSsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0wLjUpKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCw1MCkpCgp1bnVzdWFsIDwtIGRpYW1vbmRzIHw+IAogIGZpbHRlcih5PDMgfCB5PjIwKSB8PiAKICBzZWxlY3QocHJpY2UseCx5LHopIHw+IAogIGFycmFuZ2UoeSkKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDgzCmdncGxvdChkaWFtb25kcyxhZXMoeD14KSkrCiAgZ2VvbV9oaXN0b2dyYW0oKQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PXkpKSsKICBnZW9tX2hpc3RvZ3JhbSgpCgpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9eikpKwogIGdlb21faGlzdG9ncmFtKCkKCnE4MzwtIkJ5IGxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgeCx5IGFuZCB6IHZhcmlhYmxlcywgSSBjYW4gc2VlIHRoYXQgeSBhbmQgeiBoYXZlIHNpbWlsYXIgZGlzdHJpYnV0aW9uIHdoaWxlIHggaGFzIGEgd2lkZSByYW5nZSBiZXR3ZWVuIDMtOS4gSSBiZWxpZXZlIHRoYXQgeSBhbmQgeiBpcyB0aGUgbGVuZ3RoIGFuZCB3aWR0aCBzaW5jZSBkaWFtb25kcyBhcmUgdHlwaWNhbGx5IHJvdW5kIGFuZCB4IGlzIHRoZSBkZXB0aCB3aGljaCB3ZSB3b3VsZCBleHBlY3QgdG8gaGF2ZSBzb21lIHZhcmlhdGlvbi4iCmBgYAoKYGBge3J9CiNRdWVzdGlvbiA4NApnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9cHJpY2UpKSsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDI1MCkKCnE4NDwtIkJ5IGxvb2tpbmcgYXQgdGhlIHByaWNlIGRpc3RyaWJ1dGlvbiwgd2UgY2FuIHNlZSB0aGF0IHRoZSBtYWpvcml0eSBvZiBkaWFtb25kcyBoYXZlIHByaWNlcyB0aGF0IGFyZSBsZXNzIHRoYW4gNSwwMDAgZG9sbGFycy4gSW4gYWRkaXRpb24sIHRoZSBkaXN0cmlidXRpb24gc2VlbWVzIHRvIGJlIHNrZXdlZCB0byB0aGUgbGVmdC4gSSBmaW5kIGl0IHN1cHJpc2luZyB0aGF0IHRoZSBjb3VudCBmcmVxdWVuY3kgZGVjcmVhc2VzIGdyYWR1YWxseSBhZnRlciA1LDAwMCBkb2xsYXJzLiIKYGBgCgpgYGB7cn0KI1F1ZXN0aW9uIDg1CmRpYW1vbmRzIHw+IAogIGZpbHRlcihjYXJhdD09MC45OSkgfD4gCiAgc3VtbWFyaXNlKGNvdW50PW4oKSkKCmRpYW1vbmRzIHw+IAogIGZpbHRlcihjYXJhdD09MSkgfD4gCiAgc3VtbWFyaXNlKGNvdW50PW4oKSkKCnE4NTwtIlRoZXJlIGFyZSAyMyBkaWFtb25kcyB0aGF0IGFyZSAwLjk5IGNhcmF0IGFuZCAxNTU4IGRpYW1vbmRzIHRoYXQgYXJlIDEgY2FyYXQuIEkgYmVsaWV2ZSB0aGlzIGlzIGR1ZSB0byB2YXJpYXRpb24gd2l0aGluIGRpYW1vbmRzIGN1dHMuIEluIGFkZGl0aW9uLCBJIGJlbGlldmUgMSBjYXJhdCBkaWFtb25kcyBhcmUgYSBjb21tb24gc2VsZWN0aW9uLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA4NgpxODY8LSJjb29yZF9jYXJ0ZXNpYW4oKSBpcyBkaWZmZXJlbnQgdGhhbiB4bGltKCkgYW5kIHlsaW0oKSBiZWNhdXNlIGNvb3JkX2NhcnRlc2lhbigpIHpvb21zIGluIG9uIHRoZSBnZ3Bsb3Qgd2hpbGUgeGxpbSBhbmQgeWxpbSBmaWx0ZXIgdGhlIHVuZGVybGF5aW5nIGRhdGFzZXQuIFRoZSBvdXRjb21lIGlzIHNpbWlsYXIgc2luY2UgYm90aCBmdW5jdGlvbiBhcmUgbGltaXRpbmcgdGhlIHZpc2FibGUgcmFuZ2UuIElmIHRoZSBiaW53aWR0aCBmdW5jdGlvbiBpcyBub3Qgc2V0LCB0aGVuIFIgd2lsbCBmaW5kIGFuIGFwcHJvcHJpYXRlIGJpbiB3aWR0aC4gSWYgdGhlIG9iamVjdGl2ZSBpcyB0byBvbmx5IHNlZSBoYWxmIGEgYmFyLCB0aGVuIGNvb3JkX2NhcnRlc2lhbigpIGlzIHRoZSByZWNvbW1lbmRlZCBmdW5jdGlvbi4gVGhlIHlsaW0oKSBvciB4bGltKCkgd2lsbCBub3Qgd29yayBiZWNhdXNlIGl0IHdpbGwgZmlsdGVyIG91dCB0aGUgd2hvbGUgYmFyLiIKYGBgCgpgYGB7cn0KZGlhbW9uZHMyPC1kaWFtb25kcyB8PiAKICBmaWx0ZXIoYmV0d2Vlbih5LDMsMjApKQoKZGlhbW9uZHMyPC1kaWFtb25kcyB8PiAKICBtdXRhdGUoeT1pZl9lbHNlKHk8MyB8IHk+MjAsTkEseSkpCgpnZ3Bsb3QoZGlhbW9uZHMyLGFlcyh4PXgseT15KSkrCiAgZ2VvbV9wb2ludChuYS5ybSA9IFRSVUUpCmBgYAoKYGBge3J9Cm55Y2ZsaWdodHMxMzo6ZmxpZ2h0cyB8PiAKICBtdXRhdGUoCiAgICBjYW5jZWxsZWQgPSBpcy5uYShkZXBfdGltZSksCiAgICBzY2hlZF9ob3VyID0gc2NoZWRfZGVwX3RpbWUgJS8lIDEwMCwKICAgIHNjaGVkX21pbiA9IHNjaGVkX2RlcF90aW1lICUlIDEwMCwKICAgIHNjaGVkX2RlcF90aW1lID0gc2NoZWRfaG91ciArIChzY2hlZF9taW4vNjApCiAgKSB8PiAKICBnZ3Bsb3QoYWVzKHg9c2NoZWRfZGVwX3RpbWUpKSsKICBnZW9tX2ZyZXFwb2x5KGFlcyhjb2xvcj1jYW5jZWxsZWQsYmluZHdpdGg9MS80KSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA4NwpxODc8LSJIaXN0b2dyYW1zIHdpbGwgaWdub3JlIE5BIHZhbHVlcyB3aGlsZSBiYXIgY2hhcnRzIGluY2x1ZGUgTkEgdmFsdWVzLiBIaXN0b2dyYW1zIGV4Y2x1ZGUgdGhlbSBzaW5jZSB0aGV5IGRlYWwgcHJpbWFyaWx5IHdpdGggY291bnRzIHdoaWxlIGJhciBjaGFydHMgdXN1YWxseSBpbnZvbHZlIGNhdGVnb3JpZXMuIEluIHRoaXMgY2FzZSB3ZSB3b3VsZCBub3Qgd2FudCB0byBjb3VudCBOQSB2YWx1ZXMgaW4gY291bnRzIGJ1dCBpbmNsdWRlIHRoZW0gYXMgYSBjYXRlZ29yeS4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gODgKcTg4PC0ibmEucm0gaXMgYW4gYXJndW1lbnQgdGhhdCBhbGxvd3MgZm9yIHZhbHVlcyB0byBiZSBlaXRoZXIgaW5jbHVkZWQgb3IgcmVtb3ZlZCB3aXRoIHRoZSBtZWFuKCkgb3Igc3VtKCkgZnVuY3Rpb25zLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA4OQpueWNmbGlnaHRzMTM6OmZsaWdodHMgfD4gCiAgbXV0YXRlKAogICAgY2FuY2VsbGVkID0gaXMubmEoZGVwX3RpbWUpLAogICAgc2NoZWRfaG91ciA9IHNjaGVkX2RlcF90aW1lICUvJSAxMDAsCiAgICBzY2hlZF9taW4gPSBzY2hlZF9kZXBfdGltZSAlJSAxMDAsCiAgICBzY2hlZF9kZXBfdGltZSA9IHNjaGVkX2hvdXIgKyAoc2NoZWRfbWluLzYwKQogICkgfD4gCiAgZ2dwbG90KGFlcyh4PXNjaGVkX2RlcF90aW1lKSkrCiAgZ2VvbV9mcmVxcG9seShhZXMoY29sb3I9Y2FuY2VsbGVkLGJpbmR3aXRoPTEvNCkpKwogIGZhY2V0X3dyYXAofmNhbmNlbGxlZCxzY2FsZXMgPSAiZml4ZWQiKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9cHJpY2UpKSsKICBnZW9tX2ZyZXFwb2x5KGFlcyhjb2xvcj1jdXQpLGJpbndpZHRoPTMwMCxsaW5ld2lkdGg9MC43NSkKYGBgCgpgYGB7cn0KZ2dwbG90KGRpYW1vbmRzLGFlcyh4PXByaWNlLHk9YWZ0ZXJfc3RhdChkZW5zaXR5KSkpKwogIGdlb21fZnJlcXBvbHkoYWVzKGNvbG9yPWN1dCksYmlud2lkdGg9NTAwLGxpbmV3aWR0aD0wLjc1KQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9Y3V0LHk9cHJpY2UpKSsKICBnZW9tX2JveHBsb3QoKQpgYGAKCmBgYHtyfQpnZ3Bsb3QobXBnLGFlcyh4PWNsYXNzLHk9aHd5KSkrCiAgZ2VvbV9ib3hwbG90KCkKCmdncGxvdChtcGcsYWVzKHg9ZmN0X3Jlb3JkZXIoY2xhc3MsaHd5LG1lZGlhbikseT1od3kpKSsKICBnZW9tX2JveHBsb3QoKQoKZ2dwbG90KG1wZyxhZXMoeT1mY3RfcmVvcmRlcihjbGFzcyxod3ksbWVkaWFuKSx4PWh3eSkpKwogIGdlb21fYm94cGxvdCgpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTAKbnljZmxpZ2h0czEzOjpmbGlnaHRzIHw+IAogIG11dGF0ZSgKICAgIGNhbmNlbGxlZCA9IGlzLm5hKGRlcF90aW1lKSwKICAgIHNjaGVkX2hvdXIgPSBzY2hlZF9kZXBfdGltZSAlLyUgMTAwLAogICAgc2NoZWRfbWluID0gc2NoZWRfZGVwX3RpbWUgJSUgMTAwLAogICAgc2NoZWRfZGVwX3RpbWUgPSBzY2hlZF9ob3VyICsgKHNjaGVkX21pbi82MCkKICApIHw+IAogIGdncGxvdChhZXMoeD1zY2hlZF9kZXBfdGltZSx5PWFmdGVyX3N0YXQoZGVuc2l0eSkpKSsKICBnZW9tX2ZyZXFwb2x5KGFlcyhjb2xvcj1jYW5jZWxsZWQsYmluZHdpdGg9MS80KSkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiA5MQpsaWJyYXJ5KGNvcnJwbG90KQpzdW1tYXJ5KGxtKGRhdGE9ZGlhbW9uZHMscHJpY2V+LikpCm5kPC1kaWFtb25kcyB8PiAKICBzZWxlY3RfaWYoaXMubnVtZXJpYykKbTwtY29yKG5kKQpjb3JycGxvdChtKQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PXByaWNlLHk9YWZ0ZXJfc3RhdChkZW5zaXR5KSkpKwogIGdlb21fZnJlcXBvbHkoYWVzKGNvbG9yPWN1dCksYmlud2lkdGg9NTAwLGxpbmV3aWR0aD0wLjc1KQoKcTkxPC0iQWNjb3JkaW5nIHRvIG15IGNvcnJlbGF0aW9uIHBsb3QsIGl0IGFwcGVhcnMgdGhhdCB0aGUgeCwgeSwgYW5kIHogdmFyaWFibGVzIG1heSBiZSBzaWduaWZpY2FudCBpbiBwcmVkaWN0aW5nIGRpYW1vbmQgcHJpY2UuIEl0IGFwcGVhcnMgdGhhdCB0aGUgaWRlYWwgY3V0cyBzZWVtIHRvIGJlIG1vcmUgYWZmb3JkaWFibGUgdGhhbiB0aGUgb3RoZXIgY3V0cy4gSSBiZWxpZXZlIHRoYXQgdGhlIGNvbWJpbmF0aW9uIG9mIHRoZXNlIHR3byBmaW5kaW5ncyBzaG93IHRoYXQgdGhlIGRpYW1vbmQgc2l6ZSBpcyBtb3JlIHNpZ25pZmljYW50IHRoYW4gdGhlIHF1YWxpdHkgb2YgdGhlIGN1dC4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTIKZ2dwbG90KG1wZyxhZXMoeD1mY3RfcmVvcmRlcihjbGFzcyxod3ksbWVkaWFuKSx5PWh3eSkpKwogIGdlb21fYm94cGxvdCgpCgpnZ3Bsb3QobXBnLGFlcyh4PWZjdF9yZW9yZGVyKGNsYXNzLGh3eSxtZWRpYW4pLHk9aHd5KSkrCiAgZ2VvbV9ib3hwbG90KCkrCiAgY29vcmRfZmxpcCgpCnE5MjwtIkl0IGFwcGVhcnMgdGhhdCB0aGUgY29vcmRfZmxpcCgpIGZ1bmN0aW9uIHBlcmZvcm1zIHRoZSBzYW1lIGFjdGlvbiBhcyBzd2l0Y2hpbmcgdGhlIHggYW5kIHkgYXJndW1lbnRzLiIKYGBgCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQojIFF1ZXN0aW9uIDkzCmxpYnJhcnkobHZwbG90KQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9ZmN0X3Jlb3JkZXIoY3V0LHByaWNlLG1lZGlhbikseT1wcmljZSkpKwogIGdlb21fYm94cGxvdCgpKwogIGNvb3JkX2ZsaXAoKQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PWZjdF9yZW9yZGVyKGN1dCxwcmljZSxtZWRpYW4pLHk9cHJpY2UpKSsKICBnZW9tX2x2KCkrCiAgY29vcmRfZmxpcCgpCgpxOTM8LSJJIGxlYXJuZWQgZnJvbSB0aGUgbGV0dGVyIHZhbHVlIHBsb3QgdGhhdCBib3ggcGxvdHMgb2Z0ZW4gZG8gbm90IHRlbGwgdGhlIGZ1bGwgc3Rvcnkgb2YgdGhlIGRhdGEuIEluIHRoaXMgZXhhbXBsZSwgdGhlIGN1dHMgaGF2ZSBhIGxvdCBvZiBvdXRsaWVycy4gQnkgdXNpbmcgdGhlIGxldHRlciB2YWx1ZSBwbG90LCBpdCdzIG11Y2ggZWFzaWVyIHRvIHNlZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBwcmljZSBhbW9uZyB0aGUgdmFyaW91cyBjdXQgY2F0ZWdvcmllcy4gVG8gaW50ZXJwcmV0IHRoaXMgdmlhdWFsLCBvbmUgbXVzdCB1bmRlcnN0YW5kIHRoYXQgZWFjaCBsZXR0ZXIgcmVwcmVzZW50cyBhIHBlcmNlbnRpbGUgcmFuZ2UgdGhhdCBkZWNyZWFzZXMgYnkgaGFsZiBmb3IgZWFjaCBsZXR0ZXIgd2hlbiBzdGFydGluZyBmcm9tIHRoZSBjZW50ZXIuIEFzIHlvdSBjYW4gc2VlLCB0aGUgbWFqb3JpdHkgb2YgZGlhbW9uZHMgYXJlIHVuZGVyICQyLDUwMC4iCgpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDk0CmdncGxvdChkaWFtb25kcyxhZXMoeD1mY3RfcmVvcmRlcihjdXQscHJpY2UsbWVkaWFuKSx5PXByaWNlKSkrCiAgZ2VvbV92aW9saW4oKSsKICBjb29yZF9mbGlwKCkKCmdncGxvdChkaWFtb25kcyxhZXMoeD1wcmljZSkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgY29vcmRfZmxpcCgpKwogIGZhY2V0X3dyYXAofmN1dCkKCmdncGxvdChkaWFtb25kcyxhZXMoeD1wcmljZSkpKwogIGdlb21fZnJlcXBvbHkoYWVzKGNvbG9yPWN1dCksYmlud2lkdGg9NTAwLGxpbmV3aWR0aD0wLjc1KQoKZ2dwbG90KGRpYW1vbmRzLGFlcyh4PXByaWNlLHk9YWZ0ZXJfc3RhdChkZW5zaXR5KSkpKwogIGdlb21fZnJlcXBvbHkoYWVzKGNvbG9yPWN1dCksYmlud2lkdGg9NTAwLGxpbmV3aWR0aD0wLjc1KQoKcTk0PC0iVGhlIHZpb2xpbiBwbG90IGlzIGdyZWF0IGZvciBzZWVpbmcgZGlzdHJpYnV0aW9uIHNoYXBlIGJ1dCBsYWNrcyBtZWRpYW4gb3IgcGVyY2VudGlsZSBtYXJraW5ncy4gVGhlIGZhY2V0ZWQgaGlzdG9ncmFtIGlzIGNyZWF0ZSB0byBjb21wYXJlIGdyb3VvcHMgYnV0IHN0cnVnZ2xlcyB3aGVuIGEgcGFydGljdWxhciBncm91cCBoYXMgYSBmZXcgbnVtYmVyIG9mIHZhbHVlcy4gVGhlIHR3byBmcmVxdWVuY3kgcGxvdHMgYXJlIGNyZWF0ZSBmb3IgY29tcGFyaXNpbmcgZGlzdHJpYnV0aW9uIHNoYXBlIGFuZCBkZW5zaXR5IGJ1dCBsYWNrcyB0aGUgYWJpbGl0eSB0byBzZWUgZ3JvdXBpbmdzLiIKCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTUKbGlicmFyeShnZ2JlZXN3YXJtKQogZ2dwbG90Mjo6Z2dwbG90KGdncGxvdDI6Om1wZyxhZXMoY2xhc3MsIGh3eSkpICsgZ2VvbV9iZWVzd2FybSgpCiAgZ2dwbG90Mjo6Z2dwbG90KGdncGxvdDI6Om1wZyxhZXMoY2xhc3MsIGh3eSkpICsgZ2VvbV9xdWFzaXJhbmRvbSgpCiBnZ3Bsb3QyOjpnZ3Bsb3QoZ2dwbG90Mjo6bXBnLGFlcyhjbGFzcywgaHd5KSkgKyBnZW9tX3BvaW50KCkKIHE5NTwtIlRoZSB0d28gbWFpbiBmdW5jdGlvbnMgb2YgZ2diZWVzd2FybSBhcmUgZ2VvbV9zd2FybSBhbmQgcXVhc2lyYW5kb20uIGdnYmVlc3dhcm0gYWxpZ25zIHRoZSBwb2ludHMgaW4gYSB2aW9saW4gc2hhcGUgd2hpbGUgdGhlIHF1YXNpcmFuZG9tIGZ1bmN0aW9uIHNob3dzIHRoZSBwb2ludHMgaW4gYSB2aW9saW4gc2hhcGUgYWxvbmcgd2l0aCBhZGRlZCByYW5kb21uZXNzLiIKIApgYGAKCmBgYHtyfQpnZ3Bsb3QoZGlhbW9uZHMsYWVzKHg9Y3V0LHk9Y29sb3IpKSsKICBnZW9tX2NvdW50KCkKCmRpYW1vbmRzIHw+IAogIGNvdW50KGNvbG9yLGN1dCkKCmRpYW1vbmRzIHw+IAogIGNvdW50KGNvbG9yLGN1dCkgfD4gCiAgZ2dwbG90KGFlcyh4PWNvbG9yLHk9Y3V0KSkrCiAgZ2VvbV90aWxlKGFlcyhmaWxsPW4pKQpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDk1CnE5NTwtIkkgY291bGQgZmFjZXQgdGhlIGxhc3QgcGxvdCBpbiBvcmRlciB0byBtb3JlIGNsZWFybHkgc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGN1dCB3aXRoaW4gY29sb3Igb3IgY29sb3Igd2l0aGluIGN1dC4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTYKZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNvbG9yLCBmaWxsID0gY3V0KSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIikgKwogIGxhYnModGl0bGUgPSAiU2VnbWVudGVkIEJhciBDaGFydCBvZiBEaWFtb25kcyIsCiAgICAgICB4ID0gImNvbG9yIiwKICAgICAgIHkgPSAiQ291bnQiLAogICAgICAgZmlsbCA9ICJjdXQiKQpxOTY8LSJJdCBpcyBtdWNoIGVhc2llciB0byBzZWUgdGhlIGRpZmZlcmVuY2UgaW4gY29sb3IgY291bnQgd2hlbiBzd2l0Y2hpbmcgdGhlIHggYW5kIHkgYXhpcy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTcKZmxpZ2h0czwtbnljZmxpZ2h0czEzOjpmbGlnaHRzCgpueWNmbGlnaHRzMTM6OmZsaWdodHMgfD4KICBmaWx0ZXIoZGVzdD09Ik9SRCIgfCBkZXN0PT0iSUFIIikgfD4gCiAgZ3JvdXBfYnkoZGVzdCxtb250aCkgfD4gCiAgc3VtbWFyaXNlKEFGRD1tZWFuKGRlcF9kZWxheSxuYS5ybT1UUlVFLC5ncm91cHM9ImRyb3AiKSkgfD4gCiAgZ2dwbG90KGFlcyh4PWRlc3QseT1tb250aCxmaWxsPUFGRCkpKwogIGdlb21fdGlsZSgpCnE5NzwtIlRoZSBwbG90IGlzIGhhcmQgdG8gcmVhZCBiZWNhdXNlIHRoZXJlIGlzIHRvbyBtYW55IGNhdGVnb3JpZXMgYmVpbmcgY29tcGFyaWVkLiBJIGNhbiBpbXByb3ZlIHRoaXMgcGxvdCBieSB0YWtpbmcgYSBzdWJzZXQgb2YgZGVzdCBhbmQgdGhlbiBmYWNldGluZy4iCmBgYAoKYGBge3J9CmdncGxvdChzbWFsbGVyLGFlcyh4PWNhcmF0LHk9cHJpY2UpKSsKICBnZW9tX3BvaW50KGFscGhhPTEvMTAwKQpgYGAKCmBgYHtyfQpnZ3Bsb3Qoc21hbGxlcixhZXMoeD1jYXJhdCx5PXByaWNlKSkrCiAgZ2VvbV9iaW4yZCgpCgpnZ3Bsb3Qoc21hbGxlcixhZXMoeD1jYXJhdCx5PXByaWNlKSkrCiAgZ2VvbV9oZXgoKQoKZ2dwbG90KHNtYWxsZXIsYWVzKHg9Y2FyYXQseT1wcmljZSkpICsKICBnZW9tX2JveHBsb3QoYWVzKGdyb3VwPWN1dF93aWR0aChjYXJhdCwwLjEpKSx2YXJ3aWR0aCA9IFRSVUUpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTgKcTk4PC0iY3V0IHdpZHRoIGNyZWF0ZXMgYmlucyBiYXNlZCBvbiB3aWR0aCBzcGVjaWZpY2F0aW9uIGFuZCBjdXQgbnVtYmVyIGNyZWF0ZXMgbiBudW1iZXIgb2YgYmlucy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gOTkKZ2dwbG90KGRpYW1vbmRzLCBhZXMoeCA9IGNhcmF0LCB5ID0gcHJpY2UsIGNvbG9yID0gcHJpY2UpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNykgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdyA9ICJibHVlIiwgaGlnaCA9ICJyZWQiKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQ2FyYXQgUGFydGl0aW9uZWQgYnkgUHJpY2UiLAogICAgICAgeCA9ICJDYXJhdCIsCiAgICAgICB5ID0gIlByaWNlIiwKICAgICAgIGNvbG9yID0gIlByaWNlIExldmVsIikKCmdncGxvdChzbWFsbGVyLGFlcyh4PWNhcmF0LHk9cHJpY2UpKSArCiAgZ2VvbV9ib3hwbG90KGFlcyhncm91cD1jdXRfaW50ZXJ2YWwoY2FyYXQsMTApKSx2YXJ3aWR0aCA9IEZBTFNFKQpgYGAKCmBgYHtyfQojIFF1ZXN0aW9uIDEwMApnZ3Bsb3Qoc21hbGxlcixhZXMoeD1jYXJhdCx5PXByaWNlKSkgKwogIGdlb21fYm94cGxvdChhZXMoZ3JvdXA9Y3V0X2ludGVydmFsKGNhcmF0LDEwKSksdmFyd2lkdGggPSBUUlVFKQpxMTAwPC0iVGhlIHByaWNlIGRpc3RyaWJ1dGlvbiBvZiB2ZXJ5IGxhcmdlIGRpYW1vbmRzIGlzIG11Y2ggbGFyZ2VyIHRoYW4gc21hbGxlciBkaWFtb25kcy4gSSBiZWxpZXZlIHRoaXMgaXMgZXhwZWN0ZWQgc2luY2UgdGhlcmUgYXJlIGEgbG90IGxlc3Mgb2YgdGhlbSBjb21wYXJlZCB0byB0aGUgc21hbGxlciBkaWFtb25kcy4iCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTAxCmdncGxvdChzbWFsbGVyLGFlcyh4PWNhcmF0LHk9cHJpY2UpKSArCiAgZ2VvbV9ib3hwbG90KGFlcyhncm91cD1jdXRfaW50ZXJ2YWwoY2FyYXQsMTApKSx2YXJ3aWR0aCA9IFRSVUUpKwogIGZhY2V0X3dyYXAofmN1dCkKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxMDIKZGlhbW9uZHMgfD4gCiAgZmlsdGVyKHg+PTQpIHw+IAogIGdncGxvdChhZXMoeD14LHk9eSkpKwogIGdlb21fcG9pbnQoKSsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDQsMTEpLHlsaW09Yyg0LDExKSkKcTEwMjwtIkEgYmlubmVkIHBsb3QgaXMgbm90IGFzIGdvb2QgYXMgYSBzY2F0dGVycGxvdCBiZWNhdXNlIHdlJ3JlIG5vdCBhYmxlIHRvIHNlZSBvdXRsaWVycyBsaWtlIHdlIGNhbiBzZWUgaW4gdGhlIHBsb3QgYmVsb3cuIEJpbiBwbG90cyBhcmUgb25seSBnb29kIGF0IGRpc3BsYXlpbmcgb3V0bGllcnMgd2l0aGluIGEgc2luZ2xlIHZhcmlhYmxlLiIKYGBgCgpgYGB7cn0KIyBRdWVzdGlvbiAxMDMKZ2dwbG90KHNtYWxsZXIsYWVzKHg9Y2FyYXQseT1wcmljZSkpKwogIGdlb21fYm94cGxvdChhZXMoZ3JvdXA9Y3V0X251bWJlcihjYXJhdCwxMCkpKQpxMTAzPC0iVGhlIGFkdmFudGFnZSBvZiB0aGlzIGFwcHJvYWNoIGlzIHRoYXQgd2UgY2FuIGVhc2lseSBzZWUgdGhlIGRpc3RyaWJ0aW9uIGJhc2VkIG9uIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGJ1dCBpdCdzIG5vdCBjbGVhciB3aGF0IHRoZSBncm91cGluZyByYW5nZXMgYXJlLiAiCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeW1vZGVscykKCmRpYW1vbmRzIDwtIGRpYW1vbmRzIHw+IAogIG11dGF0ZSgKICAgIGxvZ19wcmljZSA9IGxvZyhwcmljZSksCiAgICBsb2dfY2FyYXQgPSBsb2coY2FyYXQpCiAgKQogIApkaWFtb25kc19maXQgPC0gbGluZWFyX3JlZygpIHw+IAogIGZpdChsb2dfcHJpY2UgfiBsb2dfY2FyYXQsIGRhdGEgPSBkaWFtb25kcykKCmRpYW1vbmRzX2F1ZyA8LSBhdWdtZW50KGRpYW1vbmRzX2ZpdCwgbmV3X2RhdGEgPSBkaWFtb25kcykgfD4gCiAgbXV0YXRlKC5yZXNpZD1leHAoLnJlc2lkKSkKCmdncGxvdChkaWFtb25kc19hdWcsYWVzKHg9Y2FyYXQseT0ucmVzaWQpKSsKICBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRpYW1vbmRzX2F1ZyxhZXMoeD1jdXQseT0ucmVzaWQpKSsKICBnZW9tX2JveHBsb3QoKQpgYGAKCiMgQ2hhcHRlciAxMTogQ29tbXVuaWNhdGlvbgpgYGB7cn0KbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKYGBge3J9CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1jbGFzcykpKwogIGdlb21fc21vb3RoKHNlPUZBTFNFKSsKICBsYWJzKAogICAgeD0iRW5naW5lIGRpc3BsYWNlbWVudCAoTCkiLAogICAgeT0iSGlnaHdheSBmdWVsIGVjb25vbXkgKG1wZykiLAogICAgY29sb3I9IkNhciB0eXBlIiwKICAgIHRpdGxlPSJGdWVsIGVmZmljaWVuY3kgZ2VuZXJhbGx5IGRlY3JlYXNlcyB3aXRoIGVuZ2luZSBzaXplIiwKICAgIHN1YnRpdGxlID0gIlR3byBzZWF0ZXJzIChzcG9ydHMgY2FycykgYXJlIGFuIGV4Y2VwdGlvbiBiZWNhdXNlIG9mIHRoZWlyIGxpZ2h0IHdlaWdodCIsCiAgICBjYXB0aW9uPSJEYXRhIGZyb20gZnVlbGVjb25vbXkuZ292IgogICAgKQogIApkZiA8LSB0aWJibGUoCiAgeD0xOjEwLAogIHk9Y3Vtc3VtKHheMikKKQoKZ2dwbG90KGRmLGFlcyh4LHkpKSsKICBnZW9tX3BvaW50KCkrCiAgbGFicygKICAgIHg9cXVvdGUoeFtpXSksCiAgICB5PXF1b3RlKHN1bSh4W2ldXjIsaT09MSxuKSkKICApCmBgYApgYGB7cn0KIyBRdWVzdGlvbiAxMDMKZ2dwbG90KG1wZyxhZXMoeD1tYW51ZmFjdHVyZXIseT1od3kpKSsKICBnZW9tX2JveHBsb3QoKSsKICBjb29yZF9mbGlwKCkrCiAgbGFicyhzdWJ0aXRsZSA9ICJUb3AgMTUgQ2FyIEJyYW5kcyIsCiAgICAgICB0aXRsZT0iVG95b3RhIGhhcyB0aGUgYmVzdCBIaWdod2F5IEdhcyBNaWxhZ2UiLAogICAgICAgY2FwdGlvbiA9ICJEYXRhIGNhcHR1cmVkIGluIDIwMjAiKQoKbXBnCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTA0CmdncGxvdChtcGcsYWVzKHg9Y3R5LHk9aHd5LGNvbG9yPWRydixzaGFwZT1kcnYpKSsKICBnZW9tX3BvaW50KCkrCiAgbGFicyh5PSJIaWdod2F5IE1QRyIseD0iQ2l0eSBNUEciLGNvbG9yPSJUeXBlIG9mIGRyaXZlIHRyYWluIixzaGFwZT0iVHlwZSBvZiBkcml2ZSB0cmFpbiIpCmBgYAoKYGBge3J9CiMgUXVlc3Rpb24gMTA1CmxpYnJhcnkocGFsbWVycGVuZ3VpbnMpCmxpYnJhcnkobHZwbG90KQpwZW5ndWlucwpnZ3Bsb3QocGVuZ3VpbnMsYWVzKHg9aXNsYW5kLHk9YmlsbF9sZW5ndGhfbW0sZmlsbD1pc2xhbmQpKSsKICBnZW9tX2x2KCkrCiAgbGFicyh0aXRsZT0iQmlzY29lIElzbGFuZCBoYXMgdGhlIGxvbmdlc3QgQmlsbCBMZW5ndGgiLGNhcHRpb249IlBhbG1lciBQZW5ndWlucyBQYWNrYWdlIix4PSJJc2xhbmQiLHk9IkJpbGwgTGVuZ3RoIixmaWxsPSJJc2xhbmQiKQpgYGAKCmBgYHtyfQpsYWJlbF9pbmZvIDwtIG1wZyB8PiAKICBncm91cF9ieShkcnYpIHw+IAogIGFycmFuZ2UoZGVzYyhkaXNwbCkpIHw+IAogIHNsaWNlX2hlYWQobj0xKSB8PiAKICBtdXRhdGUoCiAgICBkcml2ZV90eXBlPWNhc2Vfd2hlbigKICAgICAgZHJ2ID09ICJmIiB+ICJmcm9udC13aGVlbCBkcml2ZSIsCiAgICAgIGRydiA9PSAiciIgfiAicmVhci13aGVlbCBkcml2ZSIsCiAgICAgIGRydiA9PSAiNCIgfiAiNC13aGVlbCBkcml2ZSIKICAgICkKICApIHw+IAogIHNlbGVjdChkaXNwbCxod3ksZHJ2LGRyaXZlX3R5cGUpCgpsYWJlbF9pbmZvCmBgYAoKYGBge3J9CmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3ksY29sb3I9ZHJ2KSkrCiAgZ2VvbV9wb2ludChhbHBoYT0wLjMpICsKICBnZW9tX3Ntb290aChzZT1GQUxTRSkrCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IGxhYmVsX2luZm8sCiAgICBhZXMoeD1kaXNwbCx5PWh3eSxsYWJlbD1kcml2ZV90eXBlKSwKICAgIGZvbnRmYWNlID0gImJvbGQiLHNpemU9NSxoanVzdD0icmlnaHQiLHZqdXN0PSJib3R0b20iCiAgKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKZ2dwbG90KG1wZyxhZXMoeD1kaXNwbCx5PWh3eSxjb2xvcj1kcnYpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgoc2U9RkFMU0UpKwogIGdlb21fbGFiZWxfcmVwZWwoCiAgICBkYXRhPWxhYmVsX2luZm8sCiAgICBhZXMoeD1kaXNwbCx5PWh3eSxsYWJlbD1kcml2ZV90eXBlKSwKICAgIGZvbnRmYWNlPSJib2xkIixzaXplPTQsbnVkZ2VfeT0yCiAgKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpwb3RlbnRpYWxfb3V0bGllcnMgPC0gbXBnIHw+CiAgZmlsdGVyKGh3eSA+IDQwIHwgKGh3eSA+IDIwICYgZGlzcGwgPiA1KSkKICAKZ2dwbG90KG1wZywgYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGE9cG90ZW50aWFsX291dGxpZXJzLGFlcyhsYWJlbD1tb2RlbCkpKwogIGdlb21fcG9pbnQoZGF0YT1wb3RlbnRpYWxfb3V0bGllcnMsY29sb3I9InJlZCIpKwogIGdlb21fcG9pbnQoZGF0YT1wb3RlbnRpYWxfb3V0bGllcnMsIGNvbG9yID0gInJlZCIsc2l6ZT0zLHNoYXBlPSJjaXJjbGUgb3BlbiIpCmBgYAoKYGBge3J9CnRyZW5kX3RleHQgPC0gIkxhcmdlciBlbmdpbmUgc2l6ZXMgdGVuZCB0b1xuaGF2ZSBsb3dlciBmdWVsIGVjb25vbXkuIiB8PiAKICBzdHJfd3JhcCh3aWR0aD0zMCkKCmdncGxvdChtcGcsYWVzKHg9ZGlzcGwseT1od3kpKSsKICBnZW9tX3BvaW50KCkrCiAgYW5ub3RhdGUoCiAgICBnZW9tPSJsYWJlbCIseD0zLjUseT0zOCwKICAgIGxhYmVsID0gdHJlbmRfdGV4dCwKICAgIGhqdXN0PSJsZWZ0Iixjb2xvcj0icmVkIgogICkrCiAgYW5ub3RhdGUoCiAgICBnZW9tPSJzZWdtZW50IiwKICAgIHg9Myx5PTM1LHhlbmQ9NSx5ZW5kPTI1LGNvbG9yPSJyZWQiLAogICAgYXJyb3c9YXJyb3codHlwZT0iY2xvc2VkIikKICApCmBgYAoK